New file |
| | |
| | | """dialog id to 36 |
| | | |
| | | Revision ID: 1c4af61d72a5 |
| | | Revises: 0366cf835bba |
| | | Create Date: 2024-12-13 11:24:57.138214 |
| | | |
| | | """ |
| | | 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 = '1c4af61d72a5' |
| | | down_revision: Union[str, None] = '0366cf835bba' |
| | | 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.alter_column('dialogs', 'id', |
| | | existing_type=mysql.VARCHAR(length=32), |
| | | type_=sa.String(length=36), |
| | | existing_nullable=False) |
| | | op.alter_column('dialogs', 'agent_id', |
| | | existing_type=mysql.VARCHAR(length=32), |
| | | type_=sa.String(length=36), |
| | | existing_nullable=True) |
| | | op.alter_column('knowledgebase', 'id', |
| | | existing_type=mysql.VARCHAR(length=32), |
| | | type_=sa.String(length=36), |
| | | existing_nullable=False) |
| | | # ### end Alembic commands ### |
| | | |
| | | |
| | | def downgrade() -> None: |
| | | # ### commands auto generated by Alembic - please adjust! ### |
| | | op.alter_column('knowledgebase', 'id', |
| | | existing_type=sa.String(length=36), |
| | | type_=mysql.VARCHAR(length=32), |
| | | existing_nullable=False) |
| | | op.alter_column('dialogs', 'agent_id', |
| | | existing_type=sa.String(length=36), |
| | | type_=mysql.VARCHAR(length=32), |
| | | existing_nullable=True) |
| | | op.alter_column('dialogs', 'id', |
| | | existing_type=sa.String(length=36), |
| | | type_=mysql.VARCHAR(length=32), |
| | | existing_nullable=False) |
| | | # ### end Alembic commands ### |
New file |
| | |
| | | """menu table update |
| | | |
| | | Revision ID: ba24e02a6610 |
| | | Revises: ef06c24632a7 |
| | | Create Date: 2024-12-13 17:19:35.020328 |
| | | |
| | | """ |
| | | from typing import Sequence, Union |
| | | |
| | | from alembic import op |
| | | import sqlalchemy as sa |
| | | |
| | | |
| | | # revision identifiers, used by Alembic. |
| | | revision: str = 'ba24e02a6610' |
| | | down_revision: Union[str, None] = 'ef06c24632a7' |
| | | 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('menu_capacity', sa.Column('chat_id', sa.String(length=36), nullable=True)) |
| | | op.add_column('menu_capacity', sa.Column('chat_type', sa.String(length=36), nullable=True)) |
| | | # ### end Alembic commands ### |
| | | |
| | | |
| | | def downgrade() -> None: |
| | | # ### commands auto generated by Alembic - please adjust! ### |
| | | op.drop_column('menu_capacity', 'chat_type') |
| | | op.drop_column('menu_capacity', 'chat_id') |
| | | # ### end Alembic commands ### |
New file |
| | |
| | | """dialog id to update |
| | | |
| | | Revision ID: ef06c24632a7 |
| | | Revises: 1c4af61d72a5 |
| | | Create Date: 2024-12-13 16:18:18.486282 |
| | | |
| | | """ |
| | | from typing import Sequence, Union |
| | | |
| | | from alembic import op |
| | | import sqlalchemy as sa |
| | | |
| | | |
| | | # revision identifiers, used by Alembic. |
| | | revision: str = 'ef06c24632a7' |
| | | down_revision: Union[str, None] = '1c4af61d72a5' |
| | | 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('dialogs', sa.Column('mode', sa.String(length=36), nullable=True)) |
| | | op.add_column('user', sa.Column('sync_flag', sa.String(length=36), nullable=True)) |
| | | op.add_column('web_menu', sa.Column('rank', sa.Integer(), nullable=True)) |
| | | # ### end Alembic commands ### |
| | | |
| | | |
| | | def downgrade() -> None: |
| | | # ### commands auto generated by Alembic - please adjust! ### |
| | | op.drop_column('web_menu', 'rank') |
| | | op.drop_column('user', 'sync_flag') |
| | | op.drop_column('dialogs', 'mode') |
| | | # ### end Alembic commands ### |
| | |
| | | from app.models.app_token_model import AppToken |
| | | from app.models.base_model import get_db |
| | | from app.models.postgresql_base_model import get_pdb |
| | | from app.models.token_model import upsert_token |
| | | from app.models.token_model import upsert_token, update_token |
| | | from app.models.user import UserCreate, LoginData |
| | | from app.models.user_model import UserModel, UserAppModel |
| | | from app.service.auth import authenticate_user, create_access_token, is_valid_password, save_register_user, \ |
| | |
| | | from app.service.ragflow import RagflowService |
| | | from sqlalchemy.future import select |
| | | |
| | | from app.utils.password_handle import generate_password |
| | | |
| | | router = APIRouter() |
| | | |
| | |
| | | continue |
| | | try: |
| | | name = login_data.username |
| | | app_password = login_data.password |
| | | user_app = await UserAppDao(db).get_data_by_id(user.id, app["id"]) |
| | | if user_app: |
| | | name = user_app.username |
| | | app_password = user_app.decrypted_password(user_app.password) |
| | | else: |
| | | await update_user_info(db, user.id) |
| | | token = await service.login(name, login_data.password) |
| | | token = await service.login(name, app_password) |
| | | token_dict[app["id"]] = token |
| | | except Exception as e: |
| | | return Response(code=500, msg=f"Failed to login with {app['id']}: {str(e)}") |
| | |
| | | # 创建本地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() |
| | |
| | | app_register = AppRegisterDao(db).get_apps() |
| | | register_dict = {} |
| | | token = "" |
| | | app_password = await generate_password(10) |
| | | for app in app_register: |
| | | if app["id"] == RAGFLOW: |
| | | service = RagflowService(settings.fwr_base_url) |
| | |
| | | continue |
| | | try: |
| | | name = app["id"] + str(int(time.time())) |
| | | register_info = await service.register(name, user.password, token) |
| | | register_info = await service.register(name, app_password, token) |
| | | # 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)}") |
| | | user_id = await save_register_user(db, user.username, user.password, user.email, register_dict) |
| | | user_id = await save_register_user(db, user.username, user.password, user.email, app_password, register_dict) |
| | | if not user_id: |
| | | return Response(code=500, msg=f"Failed to register with app") |
| | | is_update = await update_user_group(db, user_id) |
| | | return Response(code=200, msg="User registered successfully",data={"username": user.username}) |
| | | return Response(code=200, msg="User registered successfully",data={"userFlag": user_id}) |
| | | |
| | | |
| | | @router.get("/v2/sync", response_model=Response) |
| | | async def sync_user_tenant(userFlag: str, db=Depends(get_db)): |
| | | app_register = AppRegisterDao(db).get_app_by_id(RAGFLOW) |
| | | if app_register: |
| | | is_update = await update_user_group(db, userFlag) |
| | | return Response(code=200, msg="success", data={}) |
| | |
| | | |
| | | @dialog_router.post("/create", response_model=Response) |
| | | async def create_dialog_api(dialog: dialogData, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | is_create = await create_dialog_service(db, dialog.id, dialog.name, dialog.description, dialog.icon, dialog.dialogType, current_user.id) |
| | | is_create = await create_dialog_service(db, dialog.id, dialog.name, dialog.description, dialog.icon, dialog.dialogType, dialog.mode,current_user.id) |
| | | if not is_create: |
| | | return Response(code=500, msg="role create failure", data={}) |
| | | return Response(code=200, msg="role create success", data={}) |
| | |
| | | return Response(code=500, 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() |
| | | @role_router.delete("/delete_role/{roleId}", response_model=Response) |
| | | async def delete_group(roleId: str, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | db_role = db.query(RoleModel).filter(RoleModel.id == roleId).first() |
| | | if not db_role: |
| | | return Response(code=200, msg="role does not exist") |
| | | if db_role.role_type ==2: |
| | | return Response(code=400, msg="默认角色不允许删除!") |
| | | is_edit = await delete_role_data(db, role_id) |
| | | is_edit = await delete_role_data(db, roleId) |
| | | if not is_edit: |
| | | return Response(code=500, msg="role delete failure", data={}) |
| | | return Response(code=200, msg="role delete successfully", data={}) |
| | |
| | | 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() |
| | | db_role = db.query(RoleModel).filter(RoleModel.id == role.roleId).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) |
| | | is_edit = await edit_role_status(db, role.status,role.roleId) |
| | | if not is_edit: |
| | | return Response(code=500, msg="role status edit failure", data={}) |
| | | return Response(code=200, msg="role status edit successfully", data={}) |
| | |
| | | if role.editType == 1: |
| | | if not role.roleName: |
| | | return Response(code=400, msg="The roleName cannot be empty!") |
| | | db_role = db.query(RoleModel).filter(RoleModel.id == role.role_id).first() |
| | | db_role = db.query(RoleModel).filter(RoleModel.id == role.roleId).first() |
| | | if not db_role: |
| | | return Response(code=200, msg="role does not exist") |
| | | |
| | | db_role = db.query(RoleModel).filter(RoleModel.name == role.roleName).first() |
| | | if db_role and db_role.id != role.role_id: |
| | | if db_role and db_role.id != role.roleId: |
| | | return Response(code=200, msg="role already created") |
| | | is_edit = await edit_role_resource(db, role.role_id,role.roleName, role.remark, role.roleKey, role.dataScope, role.resources, role.editType) |
| | | is_edit = await edit_role_resource(db, role.roleId,role.roleName, role.remark, role.roleKey, role.dataScope, role.resources, role.editType) |
| | | if not is_edit: |
| | | return Response(code=500, msg="role edit failure", data={}) |
| | | return Response(code=200, msg="role edit successfully", data={}) |
| | |
| | | from fastapi import APIRouter, Depends |
| | | 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 import PageParameter, UserStatus, UserInfo, LoginData, UserPassword |
| | | from app.models.user_model import UserModel |
| | | from app.service.auth import is_valid_password |
| | | from app.service.auth import is_valid_password, verify_password |
| | | 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, get_user_menus, get_user_permission, get_user_dept |
| | | edit_user_pwd, get_user_info, get_user_routers, get_user_menus, get_user_permission, get_user_dept, change_user_pwd, \ |
| | | user_data_service |
| | | |
| | | user_router = APIRouter() |
| | | |
| | |
| | | return Response(code=200, msg="user pwd reset successfully", data={}) |
| | | |
| | | |
| | | @user_router.put("/change_password", response_model=Response) |
| | | async def change_user_password(user: UserPassword, current_user: UserModel = Depends(get_current_user),db=Depends(get_db)): |
| | | user_info = db.query(UserModel).filter(UserModel.id==current_user.id).first() |
| | | if not user_info: |
| | | return Response(code=401, msg="Incorrect change password !") |
| | | if not verify_password(user.oldPassword, user_info.hashed_password): |
| | | return Response(code=400, msg="Incorrect password !") |
| | | if not is_valid_password(user.newPassword): |
| | | return Response(code=400, msg="The password must be at least 8 and contain both numbers and letters") |
| | | is_edit = await change_user_pwd(db, user_info.id, user.newPassword) |
| | | if not is_edit: |
| | | return Response(code=500, msg="user pwd change failure", data={}) |
| | | return Response(code=200, msg="user pwd change success", data={}) |
| | | |
| | | |
| | | @user_router.get("/user_info", response_model=Response) |
| | | async def user_info(current_user: UserModel = Depends(get_current_user),db=Depends(get_db)): |
| | | user_info = await get_user_info(db, current_user.id) |
| | |
| | | @user_router.get("/dept", response_model=Response) |
| | | async def user_dept_api(userId:int, current_user: UserModel = Depends(get_current_user),db=Depends(get_db)): |
| | | menus = await get_user_dept(db, userId) |
| | | return Response(code=200, msg="successfully", data=menus) |
| | | return Response(code=200, msg="successfully", data=menus) |
| | | |
| | | |
| | | @user_router.get("/user_data", response_model=Response) |
| | | async def user_data_api(userId, current_user: UserModel = Depends(get_current_user),db=Depends(get_db)): |
| | | user_info = await user_data_service(db, userId) |
| | | if not user_info: |
| | | return Response(code=500, msg="user get failure", data={}) |
| | | return Response(code=200, msg="successfully", data=user_info) |
New file |
| | |
| | | from app.models.base_model import SessionLocal |
| | | from app.service.v2.initialize_data import dialog_menu_sync, default_group_sync, default_role_sync, app_register_sync, \ |
| | | basic_agent_sync |
| | | |
| | | |
| | | async def sync_default_data(): |
| | | db = SessionLocal() |
| | | await dialog_menu_sync(db) # 小数 |
| | | await default_group_sync(db) # 默认组 |
| | | await default_role_sync(db) # 默认角色 |
| | | await app_register_sync(db) # 注册的应用 |
| | | await basic_agent_sync(db) # 开发的agent |
| | | # await default_role_sync(db) # 页面资源配置信息 |
| | | # await default_role_sync(db) # 默认的角色资源 |
| | |
| | | __mapper_args__ = { |
| | | # "order_by": 'SEQ' |
| | | } |
| | | id = Column(String(32), primary_key=True) # id |
| | | id = Column(String(36), primary_key=True) # id |
| | | create_date = Column(DateTime, default=datetime.now()) # 创建时间 |
| | | update_date = Column(DateTime, default=datetime.now(), onupdate=datetime.now()) # 更新时间 |
| | | tenant_id = Column(String(32)) # 创建人 |
| | |
| | | description = Column(Text) # 说明 |
| | | icon = Column(Text) # 图标 |
| | | status = Column(String(1), default="1") # 状态 |
| | | dialog_type = Column(String(1)) # # 平台 |
| | | agent_id = Column(String(32)) |
| | | dialog_type = Column(String(1)) # 平台 |
| | | agent_id = Column(String(36)) |
| | | mode = Column(String(36)) |
| | | |
| | | def get_id(self): |
| | | return str(self.id) |
| | |
| | | 'status': self.status, |
| | | 'agentType': self.dialog_type, |
| | | 'agentId': self.agent_id, |
| | | 'mode': self.mode, |
| | | } |
| | | |
| | | |
| | |
| | | description: Optional[str] = "" |
| | | dialogType: str |
| | | icon: str |
| | | mode: str |
| | | |
| | | |
| | | class dialogDataUpdate(BaseModel): |
| | |
| | | __mapper_args__ = { |
| | | # "order_by": 'SEQ' |
| | | } |
| | | id = Column(String(32), primary_key=True) # id |
| | | id = Column(String(36), primary_key=True) # id |
| | | name = Column(String(128)) # 名称 |
| | | create_date = Column(DateTime, default=datetime.now()) # 创建时间 |
| | | update_date = Column(DateTime, default=datetime.now(), onupdate=datetime.now()) # 更新时间 |
| | |
| | | desc = Column(String(1000)) |
| | | icon = Column(String(16)) |
| | | img = Column(String(255)) |
| | | rank = Column(Integer) |
| | | |
| | | |
| | | def to_dict(self): |
| | |
| | | menu_id = Column(Integer) |
| | | capacity_id = Column(String(36)) |
| | | capacity_type = Column(Integer) |
| | | chat_id = Column(String(36)) |
| | | chat_type = Column(String(36)) |
| | | |
| | |
| | | |
| | | |
| | | class RoleStatus(BaseModel): |
| | | role_id: str |
| | | roleId: str |
| | | status: constr(min_length=1, max_length=1, pattern='^(0|1)$') |
| | | |
| | | |
| | | class RoleEdit(BaseModel): |
| | | role_id: str |
| | | roleId: str |
| | | remark: Optional[str] = "" |
| | | roleName: Optional[str] = "" |
| | | resources: Optional[list] = [] |
| | |
| | | if db_token: |
| | | # 记录存在,进行更新 |
| | | db_token.token = access_token |
| | | for k, v in token.items(): |
| | | setattr(db_token, k.replace("app", "token"), v) |
| | | # for k, v in token.items(): |
| | | # setattr(db_token, k.replace("app", "token"), v) |
| | | else: |
| | | # 记录不存在,进行插入 |
| | | db_token = TokenModel( |
| | | user_id=user_id, |
| | | token=access_token, |
| | | ) |
| | | for k, v in token.items(): |
| | | setattr(db_token, k.replace("app", "token"), v) |
| | | # for k, v in token.items(): |
| | | # setattr(db_token, k.replace("app", "token"), v) |
| | | db.add(db_token) |
| | | |
| | | # 提交事务 |
| | |
| | | groups: Optional[list] = [] |
| | | |
| | | |
| | | |
| | | class UserPassword(BaseModel): |
| | | # userId: int |
| | | newPassword: str |
| | | oldPassword: str |
| | | |
| | | |
| | |
| | | sex = Column(String(1)) |
| | | permission = Column(String(16), default="general") |
| | | age = Column(Integer) |
| | | sync_flag = Column(String(36)) |
| | | created_at = Column(DateTime, default=datetime.now()) |
| | | updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now()) |
| | | |
| | |
| | | for ogt in self.organizations: |
| | | if ogt.id in ogt_set: |
| | | continue |
| | | print(ogt.id) |
| | | ogt_set.add(ogt.id) |
| | | for role in ogt.roles: |
| | | roles[role.id] = role.to_dict() |
| | |
| | | while parent_ogt: |
| | | if parent_ogt.id not in ogt_set: |
| | | ogt_set.add(ogt.id) |
| | | for role in ogt.roles: |
| | | for role in parent_ogt.roles: |
| | | roles[role.id] = role.to_dict() |
| | | parent_ogt = ogt.parent |
| | | parent_ogt = parent_ogt.parent |
| | | else: |
| | | break |
| | | |
| | | json['roles'] = list(roles.values()) |
| | | return json |
| | | |
| | |
| | | "app_type": self.app_type, |
| | | 'status': self.status, |
| | | } |
| | | |
| | | def encrypted_password(self, password): |
| | | @staticmethod |
| | | def encrypted_password(password): |
| | | return cipher_suite.encrypt(password.encode("utf-8")).decode("utf-8") |
| | | |
| | | def decrypted_password(self): |
| | | return cipher_suite.decrypt(self.password).decode("utf-8") |
| | | @staticmethod |
| | | def decrypted_password(password): |
| | | return cipher_suite.decrypt(password).decode("utf-8") |
| | |
| | | import re |
| | | import uuid |
| | | from datetime import datetime, timedelta |
| | | from typing import Type |
| | | from uuid import uuid4 |
| | | |
| | | from jwt import encode, decode, exceptions |
| | | from passlib.context import CryptContext |
| | |
| | | return has_digit is not None and has_letter is not None |
| | | |
| | | |
| | | async def save_register_user(db, username, password, email, register_dict): |
| | | async def save_register_user(db, username, password, email, app_password, register_dict): |
| | | user_id = "" |
| | | sync_flag = str(uuid.uuid4()) |
| | | try: |
| | | hashed_password = pwd_context.hash(password) |
| | | db_user = UserModel(username=username, hashed_password=hashed_password, email=email) |
| | | pwd = db_user.encrypted_password(password) |
| | | db_user = UserModel(username=username, hashed_password=hashed_password, email=email, sync_flag=sync_flag) |
| | | pwd = db_user.encrypted_password(app_password) |
| | | db_user.password = pwd |
| | | db_user.roles = [db.query(RoleModel).filter(RoleModel.role_type == 2).first()] |
| | | db_user.groups = [db.query(GroupModel).filter(GroupModel.group_type == 2).first()] |
| | |
| | | db.query(UserModel).filter(UserModel.id == user_id).delete() |
| | | db.commit |
| | | return False |
| | | return user_id |
| | | return sync_flag |
| | | |
| | | |
| | | async def update_user_token(db, user_id, token_dict): |
| | |
| | | # db.commit() |
| | | # db.refresh(db_user) |
| | | |
| | | is_sava = await save_register_user(db, user.username, user.password, user.email, register_dict) |
| | | # is_sava = await save_register_user(db, user.username, user.password, user.email, register_dict) |
| | | |
| | | class UserAppDao: |
| | | def __init__(self, db: Session): |
| | |
| | | |
| | | |
| | | |
| | | async def create_dialog_service(db, dialog_id, dialog_name, description, icon, dialog_type, user_id): |
| | | async def create_dialog_service(db, dialog_id, dialog_name, description, icon, dialog_type, mode, user_id): |
| | | try: |
| | | dialog_model = DialogModel(id=dialog_id,name=dialog_name, description=description,icon=icon, dialog_type=dialog_type, tenant_id=user_id, agent_id=dialog_id) |
| | | dialog_model = DialogModel(id=dialog_id,name=dialog_name, description=description,icon=icon, dialog_type=dialog_type, tenant_id=user_id, agent_id=dialog_id, mode=mode) |
| | | db.add(dialog_model) |
| | | db.commit() |
| | | db.refresh(dialog_model) |
| | |
| | | # query.filter(RoleModel.creator==user_id) |
| | | if keyword: |
| | | query = query.filter(RoleModel.name.like('%{}%'.format(keyword))) |
| | | total = query.count() |
| | | 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]} |
| | | return {"total": total, "rows": [role.to_json() for role in roles]} |
| | | |
| | | |
| | | async def create_role(db, role_name: str, description: str, role_key, data_scope, user_id): |
| | |
| | | |
| | | |
| | | async def get_bisheng_token(db, user_id: int): |
| | | token = await UserAppDao(db).get_data_by_id(user_id, BISHENG) |
| | | |
| | | token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first() |
| | | if not token: |
| | | token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first() |
| | | token = await UserAppDao(db).get_data_by_id(user_id, BISHENG) |
| | | if not token: |
| | | return None |
| | | else: |
| | | return token.access_token |
| | | return token.bisheng_token |
| | | else: |
| | | return token.bisheng_token |
| | | |
| | | |
| | | async def get_ragflow_token(db, user_id: int): |
| | | token = await UserAppDao(db).get_data_by_id(user_id, RAGFLOW) |
| | | # token = await UserAppDao(db).get_data_by_id(user_id, RAGFLOW) |
| | | token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first() |
| | | if not token: |
| | | token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first() |
| | | token = await UserAppDao(db).get_data_by_id(user_id, RAGFLOW) |
| | | if not token: |
| | | return None |
| | | else: |
| | | return token.access_token |
| | | return token.ragflow_token |
| | | else: |
| | | return token.ragflow_token |
| | | |
| | | |
| | | async def get_dify_token(db, user_id: int): |
| | | |
| | |
| | | user = db.query(UserAppModel).filter(UserAppModel.user_id == user_id, UserAppModel.app_type==app_type).first() |
| | | if not user: |
| | | return None |
| | | pwd = user.password |
| | | if app_type == RAGFLOW: |
| | | ragflow_service = RagflowService(settings.fwr_base_url) |
| | | # 登录到ragflow |
| | | try: |
| | | ragflow_token = await ragflow_service.login(user.username, user.decrypted_password()) |
| | | ragflow_token = await ragflow_service.login(user.username, user.decrypted_password(pwd)) |
| | | return ragflow_token |
| | | except Exception as e: |
| | | logger.error(e) |
| | |
| | | bisheng_service = BishengService(settings.sgb_base_url) |
| | | # 登录到毕昇 |
| | | try: |
| | | bisheng_token = await bisheng_service.login(user.username, user.decrypted_password()) |
| | | bisheng_token = await bisheng_service.login(user.username, user.decrypted_password(pwd)) |
| | | return bisheng_token |
| | | except Exception as e: |
| | | logger.error(e) |
| | |
| | | dify_service = DifyService(settings.dify_base_url) |
| | | # 登录到毕昇 |
| | | try: |
| | | dify_token = await dify_service.login(user.username, user.decrypted_password()) |
| | | dify_token = await dify_service.login(user.username, user.decrypted_password(pwd)) |
| | | return dify_token |
| | | except Exception as e: |
| | | logger.error(e) |
| | |
| | | return res |
| | | |
| | | |
| | | async def update_user_group(db, user_id): |
| | | async def update_user_group(db, sync_flag): |
| | | admin_user = db.query(UserModel).filter(UserModel.permission == "admin").first() |
| | | sync_user = db.query(UserModel).filter(UserModel.sync_flag == sync_flag).first() |
| | | if not admin_user or not sync_user: |
| | | logger.error("注册用户失败!--------") |
| | | return False |
| | | token = await get_new_token(db, admin_user.id, RAGFLOW) |
| | | # print(token) |
| | | if not token: |
| | | logger.error("注册用户获取token失败!") |
| | | return False |
| | | user_list = db.query(UserAppModel).filter(UserAppModel.app_type==RAGFLOW).all() |
| | | user = db.query(UserAppModel).filter(UserAppModel.user_id==user_id, UserAppModel.app_type == RAGFLOW).first() |
| | | user = db.query(UserAppModel).filter(UserAppModel.userFlag==sync_user.id, UserAppModel.app_type == RAGFLOW).first() |
| | | if not user: |
| | | logger.error("注册用户获取信息失败!") |
| | | return False |
| | |
| | | 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_new_token, get_dify_token |
| | | from app.utils.password_handle import generate_password |
| | | |
| | | |
| | | async def get_user_list(db, page_index: int, page_size: int, keyword: str, role_key: str, user_id): |
| | |
| | | # query.filter(UserModel.creator==user_id) |
| | | if keyword: |
| | | query = query.filter(UserModel.username.like('%{}%'.format(keyword))) |
| | | total = query.count() |
| | | 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": total, "rows": [user.to_json() for user in users]} |
| | | |
| | | |
| | | async def edit_user_status(db, status: str, user_id: int): |
| | |
| | | |
| | | 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 |
| | | app_register = AppRegisterDao(db).get_apps() |
| | | register_dict = {} |
| | | token = "" |
| | | app_password = generate_password() |
| | | 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: |
| | | token = await get_dify_token() |
| | | token = await get_dify_token(db, user_id) |
| | | 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, token) |
| | | register_info = await service.register(name, app_password, token) |
| | | # print(register_info) |
| | | register_dict[app['id']] = {"id": register_info.get("id"), "name": name, |
| | | "email": register_info.get("email")} |
| | |
| | | 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) |
| | | pwd = user_model.encrypted_password(app_password) |
| | | user_model.roles = [db.get(RoleModel, roleId) for roleId in roles] |
| | | user_model.password = pwd |
| | | if groups: |
| | |
| | | user.email = email |
| | | user.updated_at = datetime.now() |
| | | user.roles = [db.get(RoleModel, roleId) for roleId in roles] |
| | | user.groups = [db.get(GroupModel, groupId) for groupId in groups] |
| | | # user.groups = [db.get(GroupModel, groupId) for groupId in groups] |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | |
| | | async def edit_user_pwd(db, user_id, current_user_id, new_password="basic123456"): |
| | | try: |
| | | user = db.query(UserModel).filter(UserModel.id == user_id).first() |
| | | pwd = user.decrypted_password() |
| | | for app in AppRegisterDao(db).get_apps(): |
| | | if app.get("id") == RAGFLOW: |
| | | token = await get_new_token(db, user_id, app.get("id")) |
| | | ragflow_service = RagflowService(settings.fwr_base_url) |
| | | await ragflow_service.set_user_password(token, pwd, new_password) |
| | | 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.get("id"))) |
| | | # pwd = user.decrypted_password() |
| | | # for app in AppRegisterDao(db).get_apps(): |
| | | # if app.get("id") == RAGFLOW: |
| | | # token = await get_new_token(db, user_id, app.get("id")) |
| | | # ragflow_service = RagflowService(settings.fwr_base_url) |
| | | # await ragflow_service.set_user_password(token, pwd, new_password) |
| | | # 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.get("id"))) |
| | | user.hashed_password = pwd_context.hash(new_password) |
| | | user.password = user.encrypted_password(new_password) |
| | | # user.password = user.encrypted_password(new_password) |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | | db.rollback() |
| | | return False |
| | | return True |
| | | |
| | | async def change_user_pwd(db, user_id, new_password): |
| | | try: |
| | | user = db.query(UserModel).filter(UserModel.id == user_id).first() |
| | | user.hashed_password = pwd_context.hash(new_password) |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | | db.rollback() |
| | | return False |
| | | return True |
| | | |
| | | |
| | | |
| | | async def get_user_info(db, user_id): |
| | |
| | | if parent_ogt.id not in dept_set: |
| | | await role_resource(role_set, permissions, parent_ogt.roles) |
| | | dept_set.add(parent_ogt.id) |
| | | parent_ogt = parent_ogt.parent |
| | | parent_ogt = parent_ogt.parent |
| | | else: |
| | | break |
| | | tmp_dit = {} |
| | | for permission in permissions.values(): |
| | | tmp_dit[permission["parentId"]] = tmp_dit.get(permission["parentId"], []) + [permission] |
| | |
| | | |
| | | 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, DialogModel.agent_id.label("agentId")).outerjoin( |
| | | menu_list = db.query(WebMenuModel.id, WebMenuModel.title, WebMenuModel.describe, WebMenuModel.icon, WebMenuModel.desc,WebMenuModel.rank, |
| | | WebMenuModel.img, MenuCapacityModel.capacity_id, MenuCapacityModel.capacity_type, MenuCapacityModel.chat_id.label("agentId")).outerjoin( |
| | | MenuCapacityModel, WebMenuModel.id == MenuCapacityModel.menu_id).outerjoin( |
| | | DialogModel, MenuCapacityModel.capacity_id == DialogModel.id).filter(DialogModel.status=="1").all() |
| | | |
| | |
| | | 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, |
| | |
| | | 'img': menus[0].img, |
| | | 'desc': menus[0].desc, |
| | | 'dialog': menus[0].describe, |
| | | 'agentId': menus[0].agentId |
| | | 'agentId': menus[0].agentId, |
| | | 'rank': menus[0].rank |
| | | }) |
| | | return res |
| | | return sorted(res, key=lambda x: x['rank'], reverse=True) |
| | | |
| | | |
| | | async def get_user_permission(db, user_id): |
| | |
| | | knowledge_dict = {} |
| | | user = db.query(UserModel).filter_by(id=user_id).first() |
| | | parent_id = "" |
| | | print(111111111111111) |
| | | # print(111111111111111) |
| | | async def role_resource(role_set, permissions, roles): |
| | | nonlocal parent_id |
| | | for role in roles: |
| | |
| | | await role_resource(role_set, permissions, parent_ogt.roles) |
| | | dept_set.add(parent_ogt.id) |
| | | |
| | | parent_ogt = parent_ogt.parent |
| | | parent_ogt = parent_ogt.parent |
| | | else: |
| | | break |
| | | |
| | | tmp_dit = {} |
| | | for permission in permissions.values(): |
| | |
| | | res = {} |
| | | user = db.query(UserModel).filter_by(id=user_id).first() |
| | | res["rows"] = [i.to_dict() for i in user.organizations] |
| | | return res |
| | | return res |
| | | |
| | | |
| | | async def user_data_service(db, user_id): |
| | | user = db.query(UserModel).filter_by(id=user_id).first() |
| | | |
| | | |
| | | return {"roles": [i.to_dict() for i in user.roles], "user": user.to_dict()} |
| | |
| | | import json |
| | | |
| | | from Log import logger |
| | | from app.models import MenuCapacityModel, WebMenuModel, GroupModel, RoleModel |
| | | from app.models import MenuCapacityModel, WebMenuModel, GroupModel, RoleModel, DialogModel, UserModel |
| | | from app.service.v2.app_register import AppRegisterDao |
| | | |
| | | |
| | | async def dialog_menu_sync(db): |
| | |
| | | |
| | | 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) |
| | | capacity = MenuCapacityModel(menu_id=menu["id"], capacity_id=i["id"], capacity_type=i["agentType"], chat_id=i["id"] if not i["chat_id"] else i["chat_id"], chat_type=i["chat_type"]) |
| | | db.add(capacity) |
| | | menu_obj = WebMenuModel(**menu) |
| | | db.add(menu_obj) |
| | |
| | | db.add(group) |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | | logger.error(e) |
| | | |
| | | |
| | | async def app_register_sync(db): |
| | | app_dict = {} |
| | | with open("env_conf/app_register_conf.json", 'r', encoding='utf-8') as file: |
| | | # 加载JSON数据 |
| | | app_dict = json.load(file) |
| | | try: |
| | | for app_id, status in app_dict.items(): |
| | | AppRegisterDao(db).update_and_insert_app(app_id, status) |
| | | except Exception as e: |
| | | logger.error(e) |
| | | |
| | | |
| | | async def basic_agent_sync(db): |
| | | agent_list = [] |
| | | with open("env_conf/default_agent_conf.json", 'r', encoding='utf-8') as file: |
| | | # 加载JSON数据 |
| | | agent_dict = json.load(file) |
| | | agent_list = agent_dict.get("basic", []) |
| | | user = db.query(UserModel).filter_by(permission="admin").first() |
| | | for agent in agent_list: |
| | | dialog = db.query(DialogModel).filter(DialogModel.id==agent["id"]).first() |
| | | if dialog: |
| | | try: |
| | | dialog.name = agent["name"] |
| | | dialog.description = agent["description"] |
| | | dialog.icon = agent["icon"] |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | | else: |
| | | try: |
| | | dialog = DialogModel(id=agent["id"], name=agent["name"], description=agent["description"], |
| | | icon=agent["icon"], tenant_id=user.id if user else "", dialog_type="3", |
| | | agent_id=agent["id"]) |
| | | db.add(dialog) |
| | | db.commit() |
| | | db.refresh(dialog) |
| | | except Exception as e: |
| | | print(e) |
| | | db.rollback() |
| | |
| | | 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, default_group_sync, default_role_sync |
| | | |
| | | # 创建数据库引擎和会话工厂 |
| | | engine_bisheng = create_engine(settings.sgb_db_url) |
| | |
| | | print(f"Failed to sync agents: {str(e)}") |
| | | |
| | | |
| | | async def sync_web_menu(): |
| | | db = SessionLocal() |
| | | await dialog_menu_sync(db) |
| | | |
| | | |
| | | async def sync_default_data(): |
| | | db = SessionLocal() |
| | | await default_group_sync(db) |
| | | await default_role_sync(db) |
| | | |
New file |
| | |
| | | import asyncio |
| | | import random |
| | | import string |
| | | |
| | | |
| | | async def generate_password(length=10): |
| | | if length < 6: # 至少需要3位密码以包含所有必要的字符 |
| | | raise ValueError("Password length should be at least 3") |
| | | |
| | | # 确保密码中至少包含一个字母和一个数字 |
| | | password = [ |
| | | random.choice(string.ascii_uppercase), # 大写字母 |
| | | random.choice(string.ascii_lowercase), # 小写字母 |
| | | random.choice(string.digits) # 数字 |
| | | ] |
| | | |
| | | # 添加剩余的随机字符 |
| | | characters = string.ascii_letters + string.digits |
| | | password.extend(random.choice(characters) for _ in range(length - 3)) |
| | | |
| | | # 打乱密码以确保随机性 |
| | | random.shuffle(password) |
| | | |
| | | # 将列表转换为字符串 |
| | | return ''.join(password) |
| | | |
| | | if __name__ == "__main__": |
| | | # 生成一个10位的密码 |
| | | asyncio.run(generate_password(10)) |
| | | # password = generate_password(10) |
| | | # print(password) |
New file |
| | |
| | | { |
| | | "image_and_text_conversion": "", |
| | | "document_to_report": "", |
| | | "document_to_cleaning": "" |
| | | } |
New file |
| | |
| | | { |
| | | "bisheng_app": 1, |
| | | "dify_app": 1, |
| | | "ragflow_app": 1 |
| | | } |
New file |
| | |
| | | { |
| | | "basic": [ |
| | | { |
| | | "id": "basic_excel_merge", |
| | | "name": "报表合并", |
| | | "description": "报表合并", |
| | | "icon": "intellFrame4", |
| | | "agentType": "excelMerge" |
| | | }, |
| | | { |
| | | "id": "basic_excel_talk", |
| | | "name": "智能数据", |
| | | "description": "智能数据", |
| | | "icon": "intellFrame4", |
| | | "agentType": "excelTalk" |
| | | }, |
| | | { |
| | | "id": "basic_question_talk", |
| | | "name": "出题组卷", |
| | | "description": "出题组卷", |
| | | "icon": "intellFrame4", |
| | | "agentType": "questionTalk" |
| | | }, |
| | | { |
| | | "id": "basic_paper_talk", |
| | | "name": "文档出卷", |
| | | "description": "文档出卷", |
| | | "icon": "intellFrame4", |
| | | "agentType": "paperTalk" |
| | | } |
| | | ], |
| | | "bs": [] |
| | | } |
| | |
| | | "img": "/src/assets/index/2.png", |
| | | "desc": "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。", |
| | | "describe": "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。", |
| | | "agent" : [], |
| | | "dialog": ["1"] |
| | | "rank": 100, |
| | | "dialog": [ |
| | | { |
| | | "id": "1", |
| | | "chat_id": "", |
| | | "chat_type": "report", |
| | | "agentType": 2 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": 1, |
| | |
| | | "img": "/src/assets/index/6.png", |
| | | "desc": "基于您上传的报表进行合并,助您快速完成报表整合与分析", |
| | | "describe": "基于您上传的报表进行合并,助您快速完成报表整合与分析", |
| | | "agent" : [], |
| | | "dialog": ["2"] |
| | | "dialog": [ |
| | | { |
| | | "id": "2", |
| | | "chat_id": "", |
| | | "chat_type": "excelMerge", |
| | | "agentType": 1 |
| | | } |
| | | ], |
| | | "rank": 99 |
| | | }, |
| | | { |
| | | "id": 2, |
| | |
| | | "img": "/src/assets/index/5.png", |
| | | "desc": "遍历已创建的文档知识库,生成完整和准确的答案,同时显示来源文档供您参考", |
| | | "describe": "垂域知识的问答助手,针对你的提问,我们将遍历已创建的文档知识库,生成完整和准确的答案,同时显示来源文档供您参考。", |
| | | "agent" : [], |
| | | "rank": 98, |
| | | "dialog": [] |
| | | }, |
| | | { |
| | |
| | | "img": "/src/assets/index/7.png", |
| | | "desc": "个人知识库的问答助手,基于您上传的文档进行问答,支持多文档", |
| | | "describe": "个人知识库的问答助手,基于您上传的文档进行问答,支持多文档,大小在30M以内。", |
| | | "agent" : [], |
| | | "dialog": ["3"] |
| | | "rank": 97, |
| | | "dialog": [ |
| | | { |
| | | "id": "3", |
| | | "chat_id": "", |
| | | "chat_type": "report", |
| | | "agentType": 1 |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "id": 4, |
| | |
| | | "img": "/src/assets/index/1.png", |
| | | "desc": "能够理解和学习人类的语言,具备多轮对话的能力", |
| | | "describe": "我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~", |
| | | "agent" : [], |
| | | "rank": 96, |
| | | "dialog": [] |
| | | }, |
| | | { |
| | |
| | | "img": "/src/assets/index/8.png", |
| | | "desc": "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表", |
| | | "describe": "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表", |
| | | "agent" : ["3", "4"], |
| | | "rank": 95, |
| | | "dialog": [] |
| | | }, |
| | | { |
| | |
| | | "img": "/src/assets/index/7.png", |
| | | "desc": "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。", |
| | | "describe": "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。", |
| | | "agent" : ["3"], |
| | | "rank": 94, |
| | | "dialog": [] |
| | | }, |
| | | { |
| | |
| | | "img": "/src/assets/index/6.png", |
| | | "desc": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。", |
| | | "describe": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。", |
| | | "agent" : [], |
| | | "rank": 93, |
| | | "dialog": [] |
| | | }, |
| | | { |
| | |
| | | "img": "/src/assets/index/6.png", |
| | | "desc": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。", |
| | | "describe": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。", |
| | | "agent" : ["4"], |
| | | "rank": 92, |
| | | "dialog": [] |
| | | }, |
| | | { |
| | |
| | | "img": "/src/assets/index/2.png", |
| | | "desc": "基于您创建的报告格式和上传的文档内容,快速生成定制报告,并支持一键下载。", |
| | | "describe": "基于您创建的报告格式和上传的文档内容,快速生成定制报告,并支持一键下载。", |
| | | "agent" : [], |
| | | "dialog": [] |
| | | "rank": 91, |
| | | "dialog": [ |
| | | { |
| | | "id": "basic_excel_merge", |
| | | "chat_id": "basic_report_clean", |
| | | "chat_type": "reportWorkflow", |
| | | "agentType": 4 |
| | | }, |
| | | { |
| | | "id": "basic_paper_talk", |
| | | "chat_id": "basic_report_clean", |
| | | "chat_type": "reportWorkflow", |
| | | "agentType": 4 |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | |
| | | from app.api.user import user_router |
| | | from app.api.group import group_router |
| | | from app.api.role import role_router |
| | | from app.task.fetch_agent import sync_agents, initialize_agents, sync_web_menu, sync_default_data |
| | | from app.task.fetch_agent import sync_agents, initialize_agents |
| | | from app.init_config.init_run_data import sync_default_data |
| | | |
| | | |
| | | # 使用 Lifespan 事件处理程序 |
| | |
| | | # 在应用启动时同步代理 |
| | | sync_agents() |
| | | await sync_default_data() |
| | | await sync_web_menu() |
| | | yield |
| | | # 在应用关闭时执行清理操作(如果需要) |
| | | pass |