| | |
| | | import urllib |
| | | from datetime import datetime |
| | | from typing import Callable, Any |
| | | from urllib.parse import urlencode |
| | | |
| | | import jwt |
| | | # from cryptography.fernet import Fernet |
| | | from fastapi import FastAPI, Depends, HTTPException, Header |
| | | from fastapi import FastAPI, Depends, HTTPException, Header, Request |
| | | from fastapi.security import OAuth2PasswordBearer |
| | | from passlib.context import CryptContext |
| | | from pydantic import BaseModel |
| | |
| | | from starlette.websockets import WebSocket, WebSocketDisconnect |
| | | |
| | | from Log import logger |
| | | from app.models.base_model import SessionLocal |
| | | # from app.models.app_model import AppRegisterModel |
| | | from app.models.user_model import UserModel |
| | | from app.models.user_model import UserModel, UserApiTokenModel |
| | | from app.service.auth import SECRET_KEY, ALGORITHM |
| | | from app.config.config import settings |
| | | |
| | |
| | | data: list[dict] = [] |
| | | |
| | | |
| | | def verify_token(token: str) -> Any: |
| | | """ |
| | | 验证 Token 是否有效 |
| | | """ |
| | | db = SessionLocal() |
| | | try: |
| | | db_token = db.query(UserApiTokenModel).filter(UserApiTokenModel.token == token, UserApiTokenModel.is_active == 1).first() |
| | | return db_token is not None and (db_token.expires_at is None or db_token.expires_at > datetime.now()) |
| | | finally: |
| | | db.close() |
| | | |
| | | def token_required()-> Callable: |
| | | def decorated_function(request: Request)-> Any: |
| | | authorization_str = request.headers.get("Authorization") |
| | | if not authorization_str: |
| | | raise HTTPException(status_code=401, detail="Authorization` can't be empty") |
| | | authorization_list = authorization_str.split() |
| | | if len(authorization_list) < 2: |
| | | raise HTTPException(status_code=401, detail="Invalid token") |
| | | token = authorization_list[1] |
| | | objs = verify_token(token) |
| | | if not objs: |
| | | raise HTTPException(status_code=401, detail="Invalid token") |
| | | user = UserModel(username="", id=objs.user_id) |
| | | return user |
| | | return decorated_function |
| | | |
| | | def get_current_user(token: str = Depends(oauth2_scheme)): |
| | | try: |
| | | payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) |
| | | expired_time = payload.get("lex") |
| | | if not expired_time: |
| | | raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="令牌无效或已过期", |
| | | headers={"WWW-Authenticate": "Bearer"}) |
| | | if datetime.strptime(expired_time, "%Y-%m-%d %H:%M:%S") < datetime.now(): |
| | | raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="系统授权已过期!", |
| | | headers={"WWW-Authenticate": "Bearer"}) |
| | | |
| | | username: str = payload.get("sub") |
| | | if username is None: |
| | | raise HTTPException( |
| | |
| | | from app.service.dialog import get_session_history |
| | | from app.service.ragflow import RagflowService |
| | | from app.service.service_token import get_ragflow_token, get_bisheng_token |
| | | from app.task.fetch_agent import initialize_agents |
| | | # from app.task.fetch_agent import initialize_agents |
| | | |
| | | router = APIRouter() |
| | | |
| | |
| | | # -*- coding: utf-8 -*- |
| | | import json |
| | | |
| | | from fastapi import APIRouter, Depends |
| | |
| | | from sqlalchemy.ext.asyncio import AsyncSession |
| | | from app.api import Response, pwd_context, get_current_user |
| | | from app.config.config import settings |
| | | from app.config.const import chat_server, RAGFLOW, workflow_server, DIFY, TMP_DICT |
| | | from app.config.const import chat_server, RAGFLOW, workflow_server, DIFY, TMP_DICT, SYSTEM_ID, SYSTEM_STATUS_ON |
| | | from app.models import SystemDataModel |
| | | 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 |
| | |
| | | except Exception as e: |
| | | return Response(code=500, msg=f"Failed to login with {app['id']}: {str(e)}") |
| | | """ |
| | | system = db.query(SystemDataModel).filter_by(id=SYSTEM_ID).first() |
| | | if not system or system.status != SYSTEM_STATUS_ON: |
| | | return Response(code=400, msg="系统状态异常,请授权激活后操作!") |
| | | # 创建本地token |
| | | access_token = create_access_token(data={"sub": user.username, "user_id": user.id}) |
| | | access_token = create_access_token(data={"sub": user.username, "user_id": user.id, "lex": system.expired_at.strftime('%Y-%m-%d %H:%M:%S')}) |
| | | |
| | | # await update_token(db, user.id, access_token, token_dict) |
| | | # await update_user_token(db, user.id, token_dict) |
| | |
| | | import io |
| | | import time |
| | | from typing import Optional, List |
| | | |
| | | import requests |
| | |
| | | from app.models.user_model import UserModel |
| | | from app.service.basic import BasicService |
| | | from app.service.bisheng import BishengService |
| | | from app.service.files import read_file |
| | | from app.service.files import read_file, service_chat_message, generate_word_document |
| | | from app.service.v2.api_token import DfTokenDao |
| | | from app.service.difyService import DifyService |
| | | from app.service.ragflow import RagflowService |
| | |
| | | return Response(code=400, msg=str(e)) |
| | | try: |
| | | file_upload = await dify_service.upload(token, f.filename, file_content, current_user.id) |
| | | if not file_upload: |
| | | raise HTTPException(status_code=500, detail="上传文件出错") |
| | | try: |
| | | tokens = await read_file(file_content, f.filename, f.content_type) |
| | | file_upload["tokens"] = tokens |
| | |
| | | break |
| | | yield data |
| | | |
| | | return StreamingResponse(generate(), media_type="application/octet-stream") |
| | | return StreamingResponse(generate(), media_type="application/octet-stream") |
| | | |
| | | |
| | | @router.get("/message/{message_id}/download", response_model=Response) |
| | | async def chat_message_generate_docx(message_id: str, db=Depends(get_db)): |
| | | title, content = await service_chat_message(db, message_id) |
| | | if title: |
| | | print(title) |
| | | # 创建 Word 文档 |
| | | doc = await generate_word_document(title, content) |
| | | |
| | | # 保存到内存缓冲区 |
| | | buffer = io.BytesIO() |
| | | doc.save(buffer) |
| | | buffer.seek(0) |
| | | # print(2323232) |
| | | # 返回文件流 |
| | | return StreamingResponse(buffer, |
| | | media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", |
| | | headers={"Content-Disposition": f"attachment; filename={int(time.time()*1000)}.docx"}) |
| | | raise HTTPException(status_code=400, detail="Failed to generate Word document") |
| | |
| | | |
| | | from fastapi import APIRouter, Depends, Query, HTTPException |
| | | from app.api import Response, get_current_user, ResponseList |
| | | from app.models import klgParameter, klgIcon |
| | | from app.models import klgParameter, klgIcon, KlgOwner |
| | | from app.models.base_model import get_db |
| | | from app.models.user_model import UserModel |
| | | from app.service.knowledge import get_knowledge_list, create_knowledge_service, sync_knowledge_service, \ |
| | | delete_knowledge_service, update_knowledge_icon_service |
| | | delete_knowledge_service, update_knowledge_icon_service, get_knowledge_users_service, set_knowledge_owner_service, \ |
| | | add_knowledge_user_service |
| | | from typing import Optional |
| | | |
| | | knowledge_router = APIRouter() |
| | | |
| | | |
| | | @knowledge_router.get("/list", response_model=Response) |
| | | async def knowledge_list( |
| | | current: int, |
| | | pageSize: int, |
| | | keyword: str="", |
| | | status: str="", |
| | | knowledge: str="1", |
| | | location: str="", |
| | | keyword: str = "", |
| | | status: str = "", |
| | | knowledge: str = "1", |
| | | location: str = "", |
| | | current_user: UserModel = Depends(get_current_user), |
| | | db=Depends(get_db)): |
| | | if current and not pageSize: |
| | | return ResponseList(code=400, msg="缺少参数") |
| | | getknowledgelist = await get_knowledge_list(db, current_user.id, keyword, pageSize, current, status, knowledge, location) |
| | | getknowledgelist = await get_knowledge_list(db, current_user.id, keyword, pageSize, current, status, knowledge, |
| | | location) |
| | | |
| | | return Response(code=200, msg="", data=getknowledgelist) |
| | | |
| | | |
| | | @knowledge_router.post("/create", response_model=Response) |
| | | async def create_knowledge_api(klg: klgParameter, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | is_create = await create_knowledge_service(db, klg.id, klg.name, klg.description, klg.icon, klg.klgType, current_user.id) |
| | | async def create_knowledge_api(klg: klgParameter, current_user: UserModel = Depends(get_current_user), |
| | | db=Depends(get_db)): |
| | | is_create = await create_knowledge_service(db, klg.id, klg.name, klg.description, klg.icon, klg.klgType, |
| | | current_user.id) |
| | | if not is_create: |
| | | return Response(code=500, msg="role knowledge failure", data={}) |
| | | return Response(code=200, msg="role knowledge success", data={}) |
| | | |
| | | |
| | | @knowledge_router.get("/update", response_model=Response) |
| | | async def change_knowledge_api(knowledgeId: str, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | async def change_knowledge_api(knowledgeId: str, current_user: UserModel = Depends(get_current_user), |
| | | db=Depends(get_db)): |
| | | # is_create = await update_dialog_status_service(db, dialog.id, dialog.status) |
| | | # if not is_create: |
| | | # return Response(code=500, msg="dialog update failure", data={}) |
| | |
| | | return Response(code=200, msg="knowledge delete success", data={}) |
| | | |
| | | |
| | | |
| | | @knowledge_router.put("/update_icon", response_model=Response) |
| | | async def change_dialog_icon(klg: klgIcon, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | is_create = await update_knowledge_icon_service(db, klg.id, klg.icon) |
| | | if not is_create: |
| | | return Response(code=500, msg="knowledge update failure", data={}) |
| | | return Response(code=200, msg="knowledge update success", data={}) |
| | | return Response(code=200, msg="knowledge update success", data={}) |
| | | |
| | | |
| | | @knowledge_router.get("/{knowledgeId}/users", response_model=Response) |
| | | async def get_kb_users(knowledgeId: str, |
| | | current: int, |
| | | pageSize: int, |
| | | member:int = 0, |
| | | current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | kb_user = await get_knowledge_users_service(db, knowledgeId, current_user.id, current, pageSize, member) |
| | | |
| | | return Response(code=200, msg="knowledge user success", data={"rows": kb_user}) |
| | | |
| | | |
| | | @knowledge_router.post("/transfer/owner", response_model=Response) |
| | | async def transfer_kb_owner(klgOwner: KlgOwner, |
| | | current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | is_update = await set_knowledge_owner_service(db, klgOwner.knowledgeId, klgOwner.UserId, current_user.id) |
| | | if not is_update: |
| | | return Response(code=500, msg="knowledge update failure", data={}) |
| | | return Response(code=200, msg="knowledge update success", data={}) |
| | | |
| | | |
| | | @knowledge_router.get("/{knowledgeId}/join", response_model=Response) |
| | | async def join_kb_user(knowledgeId: str, |
| | | current_user: UserModel = Depends(get_current_user), db=Depends(get_db)): |
| | | is_add = await add_knowledge_user_service(db, knowledgeId, current_user.id) |
| | | if not is_add: |
| | | return Response(code=500, msg="knowledge join failure", data={}) |
| | | return Response(code=200, msg="knowledge join success", data={}) |
| | |
| | | from app.api import Response, get_current_user |
| | | from app.models.base_model import get_db |
| | | from app.models.role_model import RoleData, RoleModel |
| | | from app.models.system import SystemData |
| | | from app.models.system import SystemData, SystemLicense |
| | | from app.models.user_model import UserModel |
| | | from app.service.system import services_get_system_data, services_update_system_data, service_upload_logo_image |
| | | from app.service.system import services_get_system_data, services_update_system_data, service_upload_logo_image, \ |
| | | services_update_system_license |
| | | |
| | | system_router = APIRouter() |
| | | |
| | |
| | | if not file_name: |
| | | return Response(code=500, msg="failed", data={"logo": ""}) |
| | | return Response(code=200, msg="successfully", data={"logo": file_name}) |
| | | |
| | | |
| | | @system_router.put("/license", response_model=Response) |
| | | async def api_update_system_license(system: SystemLicense, db=Depends(get_db)): |
| | | |
| | | msg = await services_update_system_license(db, system.licenseCode) |
| | | if msg: |
| | | return Response(code=400, msg=msg, data={}) |
| | | return Response(code=200, msg="successfully", data={}) |
| | | |
| | |
| | | is_edit = await edit_user_dept(db, user.userId, user.depts) |
| | | if not is_edit: |
| | | return Response(code=500, msg="user edit failure", data={}) |
| | | return Response(code=200, msg="user edit successfully", data={}) |
| | | return Response(code=200, msg="user edit successfully", data={}) |
| | | |
| | | |
| | | @user_router.get("/ping", response_model=Response) |
| | | async def user_ping(current_user: UserModel = Depends(get_current_user)): |
| | | return Response(code=200, msg="", data={}) |
| | |
| | | import json |
| | | import uuid |
| | | from typing import List |
| | | |
| | | from typing import List |
| | | from fastapi import Depends, APIRouter, File, UploadFile |
| | | from sqlalchemy.orm import Session |
| | | from starlette.responses import StreamingResponse, Response |
| | | from werkzeug.http import HTTP_STATUS_CODES |
| | | |
| | | from app.api import get_current_user, get_api_key |
| | | from app.config.const import dialog_chat, advanced_chat, base_chat, agent_chat, workflow_chat, basic_chat, \ |
| | | smart_message_error, http_400, http_500, http_200 |
| | | from app.config.const import smart_message_error, http_400, http_500, http_200, complex_dialog_chat, \ |
| | | complex_knowledge_chat_deep, complex_knowledge_chat |
| | | from app.models import UserModel |
| | | from app.models.base_model import get_db |
| | | from app.models.v2.chat import RetrievalRequest |
| | | from app.models.v2.chat import RetrievalRequest, ChatDataRequest, ComplexChatDao |
| | | from app.models.v2.session_model import ChatData |
| | | from app.service.v2.chat import service_chat_dialog, get_chat_info, service_chat_basic, \ |
| | | service_chat_workflow, service_chat_parameters, service_chat_sessions, service_chat_upload, \ |
| | | service_chat_sessions_list, service_chat_session_log, service_chunk_retrieval, service_base_chunk_retrieval |
| | | service_chat_sessions_list, service_chat_session_log, service_chunk_retrieval, service_complex_chat, \ |
| | | service_complex_upload |
| | | |
| | | chat_router_v2 = APIRouter() |
| | | |
| | |
| | | media_type="text/event-stream") |
| | | if not session_id: |
| | | session = await service_chat_sessions(db, chatId, dialog.query) |
| | | print(session) |
| | | # print(session) |
| | | if not session or session.get("code") != 0: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: chat agent error", "status": http_500}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | | session_id = session.get("data", {}).get("id") |
| | | return StreamingResponse(service_chat_dialog(db, chatId, dialog.query, session_id, current_user.id, chat_info.mode), |
| | | return StreamingResponse(service_chat_dialog(db, chatId, dialog.query, session_id, current_user.id, chat_info.mode, chat_info.get_kb_ids()), |
| | | media_type="text/event-stream") |
| | | |
| | | @chat_router_v2.post("/agent/{chatId}/completions") |
| | |
| | | media_type="text/event-stream") |
| | | |
| | | |
| | | @chat_router_v2.post("/complex/{chatId}/completions") |
| | | @chat_router_v2.post("/develop/{chatId}/completions") |
| | | async def api_chat_dialog(chatId:str, dialog: ChatData, current_user: UserModel = Depends(get_current_user), db: Session = Depends(get_db)): # current_user: UserModel = Depends(get_current_user) |
| | | chat_info = await get_chat_info(db, chatId) |
| | | if not chat_info: |
| | |
| | | return Response(data, media_type="application/json", status_code=http_200) |
| | | |
| | | |
| | | |
| | | # @chat_router_v2.post("/conversation/mindmap") |
| | | # async def api_conversation_mindmap(chatId:str, current:int=1, current_user: UserModel = Depends(get_current_user), db: Session = Depends(get_db)): # current_user: UserModel = Depends(get_current_user) |
| | | # data = await service_chat_sessions_list(db, chatId, current, pageSize, current_user.id, keyword) |
| | | # return Response(data, media_type="application/json", status_code=http_200) |
| | | |
| | | |
| | | |
| | | @chat_router_v2.post("/retrieval") |
| | | async def retrieve_chunks(request_data: RetrievalRequest, api_key: str = Depends(get_api_key)): |
| | | records = await service_chunk_retrieval(request_data.query, request_data.knowledge_id, request_data.retrieval_setting.top_k, request_data.retrieval_setting.score_threshold, api_key) |
| | | return {"records": records} |
| | | |
| | | |
| | | @chat_router_v2.post("/complex/chat/completions") |
| | | async def api_complex_chat_completions(chat: ChatDataRequest, current_user: UserModel = Depends(get_current_user), db: Session = Depends(get_db)): # current_user: UserModel = Depends(get_current_user) |
| | | # chat_mode = chat.chatMode |
| | | if chat.isDeep == 2 and chat.chatMode == complex_knowledge_chat: |
| | | chat.chatMode = complex_knowledge_chat_deep |
| | | complex_chat = await ComplexChatDao(db).get_complex_chat_by_mode(chat.chatMode) |
| | | if complex_chat: |
| | | if not chat.sessionId: |
| | | chat.sessionId = str(uuid.uuid4()).replace("-", "") |
| | | return StreamingResponse(service_complex_chat(db, complex_chat.id, complex_chat.mode, current_user.id, chat), |
| | | media_type="text/event-stream") |
| | | else: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: 网络异常,无法生成对话结果!", "status": http_500}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | | |
| | | |
| | | @chat_router_v2.post("/complex/upload/{chatMode}") |
| | | async def api_complex_upload(chatMode:int, file: List[UploadFile] = File(...), current_user: UserModel = Depends(get_current_user), db: Session = Depends(get_db)): # current_user: UserModel = Depends(get_current_user) |
| | | status_code = http_200 |
| | | complex_chat = await ComplexChatDao(db).get_complex_chat_by_mode(chatMode) |
| | | if complex_chat: |
| | | data = await service_complex_upload(db, complex_chat.id, file, current_user.id) |
| | | if not data: |
| | | status_code = http_400 |
| | | data = "{}" |
| | | else: |
| | | status_code = http_500 |
| | | data = "{}" |
| | | return Response(data, media_type="application/json", status_code=status_code) |
| | | |
| | | |
New file |
| | |
| | | import json |
| | | import uuid |
| | | from typing import List |
| | | |
| | | from fastapi import Depends, APIRouter, File, UploadFile |
| | | from sqlalchemy.orm import Session |
| | | from werkzeug.http import HTTP_STATUS_CODES |
| | | |
| | | from app.api import get_current_user, get_api_key, Response |
| | | from app.config.const import dialog_chat, advanced_chat, base_chat, agent_chat, workflow_chat, basic_chat, \ |
| | | smart_message_error, http_400, http_500, http_200, complex_mindmap_chat |
| | | from app.models import UserModel |
| | | from app.models.base_model import get_db |
| | | from app.models.v2.chat import RetrievalRequest, ComplexChatDao |
| | | from app.models.v2.mindmap import MindmapRequest |
| | | from app.models.v2.session_model import ChatData |
| | | from app.service.v2.mindmap import service_chat_mindmap, service_message_mindmap_parse |
| | | |
| | | mind_map_router = APIRouter() |
| | | |
| | | |
| | | @mind_map_router.post("/create", response_model=Response) |
| | | async def api_chat_mindmap(mindmap: MindmapRequest, current_user: UserModel = Depends(get_current_user), db: Session = Depends(get_db)): # current_user: UserModel = Depends(get_current_user) |
| | | complex_chat = await ComplexChatDao(db).get_complex_chat_by_mode(complex_mindmap_chat) |
| | | if complex_chat: |
| | | data = await service_chat_mindmap(db, mindmap.messageId, mindmap.query, complex_chat.id,current_user.id) |
| | | if not data: |
| | | return Response(code=500, msg="create failure", data={}) |
| | | else: |
| | | return Response(code=500, msg="网络异常!failure", data={}) |
| | | return Response(code=200, msg="create success", data=data) |
| | | |
| | | |
| | | @mind_map_router.get("/{messageId}/parse", response_model=Response) |
| | | async def api_chat_mindmap(messageId: str, current_user: UserModel = Depends(get_current_user), db: Session = Depends(get_db)): # current_user: UserModel = Depends(get_current_user) |
| | | |
| | | data = await service_message_mindmap_parse(db, messageId, current_user.id) |
| | | if not data: |
| | | return Response(code=500, msg="create failure", data={}) |
| | | return Response(code=200, msg="create success", data=data) |
| | |
| | | import json |
| | | import uuid |
| | | |
| | | from fastapi import APIRouter, Depends |
| | | from fastapi.responses import JSONResponse |
| | | from starlette.responses import StreamingResponse |
| | | |
| | | from Log import logger |
| | | from app.api import Response |
| | | from app.api import Response, token_required |
| | | |
| | | from app.config.const import IMAGE_TO_TEXT, DOCUMENT_TO_CLEANING, DOCUMENT_TO_REPORT, DIFY, BISHENG, RAGFLOW, \ |
| | | DOCUMENT_IA_QUESTIONS, DOCUMENT_TO_REPORT_TITLE, DOCUMENT_TO_TITLE, DOCUMENT_TO_PAPER, \ |
| | | DOCUMENT_IA_QUESTIONS_EQUIPMENT |
| | | |
| | | from app.models.base_model import get_db |
| | | DOCUMENT_IA_QUESTIONS_EQUIPMENT, dialog_chat, workflow_chat, advanced_chat, agent_chat, base_chat |
| | | from app.models.public_api_model import DfToken |
| | | from app.service.v2.api_token import DfTokenDao |
| | | from app.service.v2.initialize_data import dialog_menu_sync, create_menu_sync, user_update_app |
| | | from app.task.sync_resources import sync_knowledge, sync_dialog, sync_agent, sync_llm, sync_resource |
| | | # from app.task.sync_resources import sync_knowledge, sync_dialog, sync_agent, sync_llm, sync_resource |
| | | from fastapi import Depends, APIRouter, File, UploadFile |
| | | from sqlalchemy.orm import Session |
| | | from app.config.const import smart_message_error, http_400, http_500, http_200, complex_dialog_chat |
| | | from app.models import UserModel |
| | | from app.models.base_model import get_db |
| | | from app.models.v2.session_model import ChatData |
| | | from app.service.v2.chat import service_chat_dialog, get_chat_info, service_chat_sessions, service_chat_workflow |
| | | |
| | | public_api = APIRouter() |
| | | |
| | |
| | | return Response(code=500, msg=str(e), data={}) |
| | | |
| | | return Response(code=200, msg="success", data={}) |
| | | |
| | | |
| | | @public_api.post("/chat/{chatId}/completions") |
| | | async def api_chat_dialog(chatId:str, dialog: ChatData, current_user: UserModel = Depends(token_required),db: Session = Depends(get_db)): # current_user: UserModel = Depends(get_current_user) |
| | | chat_info = await get_chat_info(db, chatId) |
| | | if not chat_info: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: parameter exception", "status": http_400}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | | if chat_info.mode == dialog_chat: |
| | | |
| | | session_id = dialog.sessionId |
| | | if not dialog.query: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: question cannot be empty.", "status": http_400}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | | if not session_id: |
| | | session = await service_chat_sessions(db, chatId, dialog.query) |
| | | # print(session) |
| | | if not session or session.get("code") != 0: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: chat agent error", "status": http_500}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | | session_id = session.get("data", {}).get("id") |
| | | return StreamingResponse(service_chat_dialog(db, chatId, dialog.query, session_id, current_user.id, chat_info.mode), |
| | | media_type="text/event-stream") |
| | | elif chat_info.mode == workflow_chat: |
| | | chat_info = await get_chat_info(db, chatId) |
| | | if not chat_info: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: parameter exception", "status": http_400}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | | session_id = dialog.sessionId |
| | | if not session_id: |
| | | session_id = str(uuid.uuid4()).replace("-", "") |
| | | return StreamingResponse(service_chat_workflow(db, chatId, dialog, session_id, current_user.id, chat_info.mode), |
| | | media_type="text/event-stream") |
| | | |
| | | elif chat_info.mode == advanced_chat or chat_info.mode == agent_chat or chat_info.mode == base_chat: |
| | | chat_info = await get_chat_info(db, chatId) |
| | | if not chat_info: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: parameter exception", "status": http_400}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | | session_id = dialog.sessionId |
| | | if not session_id: |
| | | session_id = str(uuid.uuid4()).replace("-", "") |
| | | return StreamingResponse(service_chat_workflow(db, chatId, dialog, session_id, current_user.id, chat_info.mode), |
| | | media_type="text/event-stream") |
| | | else: |
| | | error_msg = json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: unknown chat", "status": http_400}) |
| | | return StreamingResponse(f"data: {error_msg}\n\n", |
| | | media_type="text/event-stream") |
| | |
| | | |
| | | ### ----------dify------api token |
| | | ### ----------df------api token |
| | | DOCUMENT_TO_CLEANING = "document_to_cleaning" |
| | | DOCUMENT_TO_REPORT = "document_to_report" |
| | | IMAGE_TO_TEXT = "image_and_text_conversion" |
| | |
| | | agent_chat = "agent-chat" |
| | | base_chat = "chat" |
| | | basic_chat = "agent-basic" |
| | | complex_chat = "complex-chat" |
| | | |
| | | |
| | | ### ------------------------------ |
| | |
| | | |
| | | ###-------------------------------system------------------------------------------------- |
| | | SYSTEM_ID = 1 |
| | | SYSTEM_STATUS_EXPIRED = 2 |
| | | SYSTEM_STATUS_ON = 1 |
| | | SYSTEM_STATUS_OFF = 0 |
| | | |
| | | ### --------------------------------complex mode---------------------------------------------- |
| | | complex_dialog_chat = 1 # 文档和基础对话 |
| | | complex_network_chat = 2 # 联网对话 |
| | | complex_knowledge_chat = 3 # 知识库对话 |
| | | complex_deep_chat = 6 |
| | | complex_mindmap_chat = 5 # 思维导图 |
| | | complex_content_optimization_chat = 4 # 内容优化 |
| | | complex_clean_chat = 7 # 清洗 |
| | | complex_title_chat = 8 # 小标题 |
| | | complex_report_chat = 9 # 报告 |
| | | complex_knowledge_chat_deep = 10 # 知识库对话-深度对话 |
| | | |
| | | |
| | | ### --------------------------------basic develop agent--------------------------------------------------- |
| | | basic_report_talk ="basic_report_talk" |
| | |
| | | password: gAAAAABnvAq8bErFiR9x_ZcODjUeOdrDo8Z5UVOzyqo6SxIhAvLpw81kciQN0frwIFVfY9wrxH1WqrpTICpEwfH7r2SkLjS7SQ== |
| | | |
| | | chat_server: |
| | | id: fe24dd2c9be611ef92880242ac160006 |
| | | account: user@example.com |
| | | password: gAAAAABnvs3e3fZOYfUUAJ6uT80dkhNeN7rhylzZErTWRZThNSLzMbZGetPCe9A2BJ86V0nZBLMNNu8w6rWp4dC7JxYxByJcow== |
| | | id: a1738c92a0df11ef89fd0242ac130006 |
| | | account: zhao1@example.com |
| | | password: gAAAAABn7R9VgyoD8z7Yiw3PfChh74n-thNyBpLTYXa-_EwIBIFXft0XFz3sjX1-u0ovYkBzlkXyHQiCOzil_bXUQF6SFAWPKw== |
| | | |
| | | workflow_server: |
| | | account: basic@mail.com |
| | | password: gAAAAABnvs5i7xUn9pb2szCozJciGSiWPGv80PH_2HFFzNM2r1ZLTOQqftnUso_bvchtmwAmccfNrf53sf9_WMFVTc0hjTKRRQ== |
| | | account: zqg@mail.com |
| | | password: gAAAAABn7R6WnM9b5vUMsWyBKF7NS481rI4m-UBPIRpUNu9xPf_g2LE8OjQfL96r1ZL-pu1Are89_fWbAI5kE23_FMWVb2nzQw== |
| | |
| | | secret_key: your-secret-key |
| | | sgb_base_url: http://192.168.20.119:13001 |
| | | sgb_websocket_url: ws://192.168.20.119:13001 |
| | | fwr_base_url: http://192.168.20.116:11080 |
| | | fwr_base_url: http://192.168.20.119:11080 |
| | | database_url: mysql+pymysql://root:infini_rag_flow@192.168.20.119:5455/rag_basic |
| | | sgb_db_url: mysql+pymysql://root:1234@192.168.20.119:13306/bisheng |
| | | fwr_db_url: mysql+pymysql://root:infini_rag_flow@192.168.20.116:15455/rag_flow |
| | | fwr_db_url: mysql+pymysql://root:infini_rag_flow@192.168.20.119:15455/rag_flow |
| | | PUBLIC_KEY: | |
| | | -----BEGIN PUBLIC KEY----- |
| | | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArq9XTUSeYr2+N1h3Afl/z8Dse/2yD0ZGrKwx+EEEcdsBLca9Ynmx3nIB5obmLlSfmskLpBo0UACBmB5rEjBp2Q2f3AG3Hjd4B+gNCG6BDaawuDlgANIhGnaTLrIqWrrcm4EMzJOnAOI1fgzJRsOOUEfaS318Eq9OVO3apEyCCt0lOQK6PuksduOjVxtltDav+guVAA068NrPYmRNabVKRNLJpL8w4D44sfth5RvZ3q9t+6RTArpEtc5sh5ChzvqPOzKGMXW83C95TxmXqpbK6olN4RevSfVjEAgCydH6HN6OhtOQEcnrU97r9H0iZOWwbw3pVrZiUkuRD1R56Wzs2wIDAQAB |
| | |
| | | "mode": "agent-basic" |
| | | } |
| | | ], |
| | | "bs": [] |
| | | "complex": [ |
| | | { |
| | | "id": "9992ba72fff111ef8d890242ac120004", |
| | | "name": "知识库专家", |
| | | "description": "知识库专家", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 3, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "1", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "ad127cb5-a1ef-49a3-82ed-6467a670fd10", |
| | | "name": "文档分析专家", |
| | | "description": "文档分析专家", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 1, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "4", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "c6a9fda3-bfb8-40ef-9510-545766c7d6a0", |
| | | "name": "联网搜索专家", |
| | | "description": "联网搜索专家", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 2, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "4", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "1974a79d-35bf-446d-95ed-0724380ea65a", |
| | | "name": "语段优化专家", |
| | | "description": "语段优化专家", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 4, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "4", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "8c6b05e7-da35-4aa4-8874-32b5bba93e7a", |
| | | "name": "思维导图专家", |
| | | "description": "思维导图专家", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 5, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "4", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "8c6b05e7-da35-4aa4-8874-32b5bba93111", |
| | | "name": "清洗工作流", |
| | | "description": "清洗工作流", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 7, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "4", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "8c6b05e7-da35-4aa4-8874-32b5bba93222", |
| | | "name": "小标题工作流", |
| | | "description": "小标题工作流", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 8, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "4", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "8c6b05e7-da35-4aa4-8874-32b5bba9333", |
| | | "name": "报告生成工作流", |
| | | "description": "报告生成工作流", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 9, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "4", |
| | | "mode": "complex-chat" |
| | | }, |
| | | { |
| | | "id": "8f3e8d9c0bab11f0896e0242ac120006", |
| | | "name": "知识库专家-深度", |
| | | "description": "知识库专家", |
| | | "icon": "intellFrame4", |
| | | "chat_mode": 10, |
| | | "parameters": { |
| | | }, |
| | | "dialogType": "1", |
| | | "mode": "complex-chat" |
| | | } |
| | | ] |
| | | } |
| | |
| | | "rank": 91, |
| | | "dialog": [ |
| | | { |
| | | "id": "87b8e17c-594d-424f-b9f8-0b56036904c9", |
| | | "chat_id": "basic_report_clean", |
| | | "chat_type": "reportWorkflow", |
| | | "agentType": 4 |
| | | }, |
| | | { |
| | | "id": "61d26deb-9371-4f9c-b61b-b9f9a24a9188", |
| | | "chat_id": "basic_report_clean", |
| | | "chat_type": "reportWorkflow", |
| | | "agentType": 4 |
| | | }, |
| | | { |
| | | "id": "d6eea92d-444a-4658-b9e7-9ab7bd5cb19d", |
| | | "id": "basic_report_talk", |
| | | "chat_id": "basic_report_clean", |
| | | "chat_type": "reportWorkflow", |
| | | "agentType": 4 |
| | |
| | | smart_system: |
| | | title: SmartAI大模型平台 |
| | | desc: SmartAI大模型平台 |
| | | version: 1.0.3 |
| | |
| | | from app.models.base_model import SessionLocal |
| | | from app.service.v2.initialize_data import dialog_menu_sync, default_group_sync, default_role_sync, \ |
| | | basic_agent_sync, admin_account_sync, sync_rg_api_token |
| | | basic_agent_sync, admin_account_sync, sync_rg_api_token, sync_complex_api_token, system_license_sync |
| | | from app.task.sync_account_token import sync_token |
| | | |
| | | |
| | |
| | | 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 admin_account_sync(db) # |
| | | await sync_rg_api_token(db) # |
| | | await sync_token() # 启动同步token任务 |
| | | await admin_account_sync(db) # 管理员账号 |
| | | await sync_rg_api_token(db) # rg token |
| | | await sync_token() # 账号token登录 |
| | | await sync_complex_api_token(db) # 账号token登录 |
| | | await system_license_sync(db) # 同步系统license |
| | | |
| | | except Exception as e: |
| | | print(e) |
| | | finally: |
| | | db.close() |
| | | # await default_role_sync(db) # 页面资源配置信息 |
| | | # await default_role_sync(db) # 默认的角色资源 |
| | | |
| | | |
| | |
| | | from .menu_model import * |
| | | from .label_model import * |
| | | from .v2.session_model import * |
| | | from .v2.chat import * |
| | | from .v2.mindmap import * |
| | | from .system import * |
| | | |
| | | |
| | |
| | | import json |
| | | from datetime import datetime |
| | | from typing import Optional |
| | | |
| | |
| | | # agent_id = Column(String(36)) |
| | | mode = Column(String(36)) |
| | | parameters = Column(Text) |
| | | kb_ids = Column(String(128)) |
| | | |
| | | def get_id(self): |
| | | return str(self.id) |
| | |
| | | 'mode': self.mode, |
| | | } |
| | | |
| | | def get_kb_ids(self): |
| | | return json.loads(self.kb_ids) if self.kb_ids else [] |
| | | |
| | | |
| | | class ConversationModel(Base): |
| | | __tablename__ = 'conversation' |
| | |
| | | def get_id(self): |
| | | return str(self.id) |
| | | |
| | | def to_json(self): |
| | | def to_json(self, user_id=""): |
| | | return { |
| | | 'id': self.id, |
| | | 'name': self.name, |
| | |
| | | 'status': self.status, |
| | | 'documents': self.documents if self.documents else 0, |
| | | 'icon': self.icon, |
| | | 'embd_id': self.embd_id |
| | | 'embd_id': self.embd_id, |
| | | 'link': True if (self.tenant_id == user_id or user_id == "admin" ) and self.permission == "team" else False, |
| | | } |
| | | def __repr__(self): |
| | | return '<Knowledge name:%r url:%r>\n' % (self.name, self.id) |
| | |
| | | |
| | | class klgIcon(BaseModel): |
| | | id: str |
| | | icon: str |
| | | icon: str |
| | | |
| | | |
| | | |
| | | class KnowledgeUserModel(Base): |
| | | __tablename__ = 'knowledgebase_user' |
| | | |
| | | id = Column(Integer, primary_key=True) # id |
| | | kb_id = Column(String(36)) |
| | | user_id = Column(Integer) |
| | | create_date = Column(DateTime, default=datetime.now()) # 创建时间 |
| | | update_date = Column(DateTime, default=datetime.now(), onupdate=datetime.now()) # 更新时间 |
| | | status = Column(Integer) # 状态 |
| | | |
| | | |
| | | |
| | | def get_id(self): |
| | | return str(self.id) |
| | | |
| | | def to_json(self, user_id=""): |
| | | return { |
| | | 'id': self.id, |
| | | 'kb_id': self.kb_id, |
| | | 'create_time': self.create_date.strftime('%Y-%m-%d %H:%M:%S'), |
| | | 'update_time': self.update_date.strftime('%Y-%m-%d %H:%M:%S'), |
| | | 'user_id': self.user_id, |
| | | 'status': self.status, |
| | | 'owner': True if str(self.user_id) == user_id else False, |
| | | } |
| | | def __repr__(self): |
| | | return '<Knowledge name:%r url:%r>\n' % (self.name, self.id) |
| | | |
| | | |
| | | |
| | | class KlgOwner(BaseModel): |
| | | knowledgeId: str |
| | | UserId: int |
| | |
| | | id = Column(Integer, primary_key=True, index=True) |
| | | title = Column(String(255)) |
| | | desc = Column(String(1000)) |
| | | version = Column(String(32)) |
| | | machine_id = Column(String(255)) |
| | | license_code = Column(String(1000)) |
| | | status = Column(Integer, default=0) |
| | | expired_at = Column(DateTime) |
| | | created_at = Column(DateTime, default=datetime.now()) |
| | | updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now()) |
| | | |
| | |
| | | # 'id': self.id, |
| | | 'title': self.title, |
| | | 'desc': self.desc, |
| | | 'version': self.version, |
| | | 'machine_id': self.machine_id, |
| | | 'license_code': self.license_code, |
| | | 'status': self.status, |
| | | 'expired_at': self.expired_at.strftime('%Y-%m-%d %H:%M') if self.expired_at else '', |
| | | } |
| | | |
| | | def __repr__(self): |
| | |
| | | title: str |
| | | desc: str |
| | | logo: str |
| | | |
| | | class SystemLicense(BaseModel): |
| | | licenseCode: str |
| | | |
| | |
| | | 'password': self.password, |
| | | 'access_token': self.access_token, |
| | | 'refresh_token': self.refresh_token, |
| | | } |
| | | |
| | | |
| | | |
| | | class UserApiTokenModel(Base): |
| | | __tablename__ = "user_api_token" |
| | | id = Column(Integer, primary_key=True) |
| | | user_id = Column(Integer) |
| | | token = Column(String(40), index=True) |
| | | created_at = Column(DateTime, default=datetime.now()) |
| | | updated_at = Column(DateTime, default=datetime.now()) |
| | | expires_at = Column(DateTime) |
| | | is_active = Column(Integer, default=1) |
| | | |
| | | def to_json(self): |
| | | return { |
| | | 'id': self.id, |
| | | 'account': self.username, |
| | | 'createTime': self.created_at, |
| | | 'updateTime': self.updated_at, |
| | | 'password': self.password, |
| | | 'access_token': self.access_token, |
| | | 'refresh_token': self.refresh_token, |
| | | } |
| | |
| | | from pydantic import BaseModel |
| | | import json |
| | | from datetime import datetime |
| | | from typing import List, Optional |
| | | |
| | | from pydantic import BaseModel |
| | | from sqlalchemy import Column, Integer, String, BigInteger, ForeignKey, DateTime, Text, TEXT |
| | | from sqlalchemy.orm import Session |
| | | |
| | | from app.config.const import Dialog_STATSU_DELETE, Dialog_STATSU_ON, complex_knowledge_chat, complex_knowledge_chat_deep |
| | | from app.models.base_model import Base |
| | | from app.utils.common import current_time |
| | | |
| | | |
| | | class RetrievalSetting(BaseModel): |
| | |
| | | query: str |
| | | retrieval_setting: RetrievalSetting |
| | | |
| | | class ChatDataRequest(BaseModel): |
| | | sessionId: str |
| | | parentId: Optional[str] = "" |
| | | query: str |
| | | chatMode: Optional[int] = 1 # 1= 普通对话,2=联网,3=知识库,4=深度 |
| | | isDeep: Optional[int] = 1 # 1= 普通, 2=深度 |
| | | optimizeType: Optional[str] = "" # 优化类型:润色,扩写,缩写,调整语气,自定义 |
| | | knowledgeId: Optional[list] = [] |
| | | files: Optional[list] = [] |
| | | |
| | | |
| | | def to_dict(self): |
| | | return { |
| | | "sessionId": self.sessionId, |
| | | "query": self.query, |
| | | "chatMode": self.chatMode, |
| | | "knowledgeId": self.knowledgeId, |
| | | "files": self.files, |
| | | "isDeep": self.isDeep, |
| | | "optimizeType": self.optimizeType, |
| | | "parentId": self.parentId, |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | class ComplexChatModel(Base): |
| | | __tablename__ = 'complex_chat' |
| | | __mapper_args__ = { |
| | | # "order_by": 'SEQ' |
| | | } |
| | | 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(36)) # 创建人 |
| | | name = Column(String(255)) # 名称 |
| | | description = Column(Text) # 说明 |
| | | icon = Column(Text, default="intelligentFrame1") # 图标 |
| | | status = Column(String(1), default="1") # 状态 |
| | | dialog_type = Column(String(1)) # 平台 |
| | | mode = Column(String(36)) |
| | | parameters = Column(Text) |
| | | chat_mode = Column(Integer) #1= 普通对话,2=联网,3=知识库,4=深度 |
| | | |
| | | def to_json(self): |
| | | return { |
| | | 'id': self.id, |
| | | 'create_date': self.create_date.strftime('%Y-%m-%d %H:%M:%S'), |
| | | 'update_date': self.update_date.strftime('%Y-%m-%d %H:%M:%S'), |
| | | 'user_id': self.tenant_id, |
| | | 'name': self.name, |
| | | 'description': self.description, |
| | | 'icon': self.icon, |
| | | 'status': self.status, |
| | | 'agentType': self.dialog_type, |
| | | 'mode': self.mode, |
| | | } |
| | | |
| | | class ComplexChatDao: |
| | | def __init__(self, db: Session): |
| | | self.db = db |
| | | |
| | | async def create_complex_chat(self, chat_id: str, **kwargs) -> ComplexChatModel: |
| | | new_session = ComplexChatModel( |
| | | id=chat_id, |
| | | create_date=current_time(), |
| | | update_date=current_time(), |
| | | **kwargs |
| | | ) |
| | | self.db.add(new_session) |
| | | self.db.commit() |
| | | self.db.refresh(new_session) |
| | | return new_session |
| | | |
| | | async def get_complex_chat_by_id(self, chat_id: str) -> ComplexChatModel | None: |
| | | session = self.db.query(ComplexChatModel).filter_by(id=chat_id).first() |
| | | return session |
| | | |
| | | async def update_complex_chat_by_id(self, chat_id: str, session, message: dict, conversation_id=None) -> ComplexChatModel | None: |
| | | if not session: |
| | | session = await self.get_complex_chat_by_id(chat_id) |
| | | if session: |
| | | try: |
| | | # TODO |
| | | session.update_date = current_time() |
| | | self.db.commit() |
| | | self.db.refresh(session) |
| | | except Exception as e: |
| | | # logger.error(e) |
| | | self.db.rollback() |
| | | return session |
| | | |
| | | async def update_or_insert_by_id(self, chat_id: str, **kwargs) -> ComplexChatModel: |
| | | existing_session = await self.get_complex_chat_by_id(chat_id) |
| | | if existing_session: |
| | | return await self.update_complex_chat_by_id(chat_id, existing_session, kwargs.get("message")) |
| | | |
| | | existing_session = await self.create_complex_chat(chat_id, **kwargs) |
| | | return existing_session |
| | | |
| | | async def delete_complex_chat(self, chat_id: str) -> None: |
| | | session = await self.get_complex_chat_by_id(chat_id) |
| | | if session: |
| | | self.db.delete(session) |
| | | self.db.commit() |
| | | |
| | | async def aget_complex_chat_ids(self) -> List: |
| | | session_list = self.db.query(ComplexChatModel).filter(ComplexChatModel.status!=Dialog_STATSU_DELETE).all() |
| | | |
| | | return [i.id for i in session_list] |
| | | |
| | | def get_complex_chat_ids(self) -> List: |
| | | session_list = self.db.query(ComplexChatModel).filter(ComplexChatModel.status!=Dialog_STATSU_DELETE).all() |
| | | |
| | | return [i.id for i in session_list] |
| | | |
| | | async def get_complex_chat_by_mode(self, chat_mode: int) -> ComplexChatModel | None: |
| | | session = self.db.query(ComplexChatModel).filter(ComplexChatModel.chat_mode==chat_mode, ComplexChatModel.status==Dialog_STATSU_ON).first() |
| | | return session |
| | | |
| | | |
| | | |
| | | class ComplexChatSessionModel(Base): |
| | | __tablename__ = "complex_chat_sessions" |
| | | |
| | | |
| | | id = Column(String(36), primary_key=True) |
| | | chat_id = Column(String(36)) |
| | | session_id = Column(String(36), index=True) |
| | | create_date = Column(DateTime, default=current_time, index=True) # 创建时间,默认值为当前时区时间 |
| | | update_date = Column(DateTime, default=current_time, onupdate=current_time) # 更新时间,默认值为当前时区时间,更新时自动更新 |
| | | tenant_id = Column(Integer, index=True) # 创建人 |
| | | agent_type = Column(Integer) # 1=rg, 3=basic,4=df |
| | | message_type = Column(Integer) # 1=用户,2=机器人,3=系统 |
| | | content = Column(TEXT) |
| | | mindmap = Column(TEXT) |
| | | query = Column(TEXT) |
| | | node_data = Column(TEXT) |
| | | event_type = Column(String(16)) |
| | | conversation_id = Column(String(36)) |
| | | chat_mode = Column(Integer) # 1= 普通对话,2=联网,3=知识库,4=深度 |
| | | |
| | | # to_dict 方法 |
| | | def to_dict(self): |
| | | return { |
| | | 'session_id': self.id, |
| | | 'name': self.name, |
| | | 'agent_type': self.agent_type, |
| | | 'chat_id': self.agent_id, |
| | | 'event_type': self.event_type, |
| | | 'session_type': self.session_type if self.session_type else 0, |
| | | 'create_date': self.create_date.strftime("%Y-%m-%d %H:%M:%S"), |
| | | 'update_date': self.update_date.strftime("%Y-%m-%d %H:%M:%S"), |
| | | } |
| | | |
| | | def log_to_json(self): |
| | | query = {} |
| | | if self.query: |
| | | query = json.loads(self.query) |
| | | if self.message_type == 1: |
| | | return { |
| | | 'id': self.id, |
| | | 'role': "user", |
| | | 'content': self.content, |
| | | 'files': query.get("files", []), |
| | | } |
| | | else: |
| | | |
| | | res = { |
| | | 'id': self.id, |
| | | 'role': "assistant", |
| | | 'answer': self.content, |
| | | 'chat_mode': self.chat_mode, |
| | | "parentId": query.get("parentId"), |
| | | "isDeep": query.get("isDeep", 1), |
| | | "mindmap": True if self.mindmap else False, |
| | | } |
| | | if self.chat_mode == complex_knowledge_chat or self.chat_mode == complex_knowledge_chat_deep: |
| | | res['reference'] = json.loads(self.node_data) if self.node_data else {} |
| | | else: |
| | | res['node_list'] = json.loads(self.node_data) if self.node_data else [] |
| | | return res |
| | | |
| | | |
| | | class ComplexChatSessionDao: |
| | | def __init__(self, db: Session): |
| | | self.db = db |
| | | |
| | | async def get_session_by_session_id(self, session_id: str, chat_id:str) -> ComplexChatSessionModel | None: |
| | | session = self.db.query(ComplexChatSessionModel).filter_by(chat_id=chat_id, session_id=session_id, message_type=2).first() |
| | | return session |
| | | |
| | | async def create_session(self, message_id: str, **kwargs) -> ComplexChatSessionModel: |
| | | new_session = ComplexChatSessionModel( |
| | | id=message_id, |
| | | create_date=current_time(), |
| | | update_date=current_time(), |
| | | **kwargs |
| | | ) |
| | | self.db.add(new_session) |
| | | self.db.commit() |
| | | self.db.refresh(new_session) |
| | | return new_session |
| | | |
| | | async def get_session_by_id(self, message_id: str) -> ComplexChatSessionModel | None: |
| | | session = self.db.query(ComplexChatSessionModel).filter_by(id=message_id).first() |
| | | return session |
| | | |
| | | async def update_mindmap_by_id(self, message_id: str, mindmap:str) -> ComplexChatSessionModel | None: |
| | | # print(message) |
| | | |
| | | session = await self.get_session_by_id(message_id) |
| | | if session: |
| | | try: |
| | | |
| | | session.mindmap = mindmap |
| | | session.update_date = current_time() |
| | | self.db.commit() |
| | | self.db.refresh(session) |
| | | except Exception as e: |
| | | # logger.error(e) |
| | | self.db.rollback() |
| | | return session |
| | | |
| | | async def update_or_insert_by_id(self, session_id: str, **kwargs) -> ComplexChatSessionModel: |
| | | existing_session = await self.get_session_by_id(session_id) |
| | | if existing_session: |
| | | return await self.update_session_by_id(session_id, existing_session, kwargs.get("message")) |
| | | |
| | | existing_session = await self.create_session(session_id, **kwargs) |
| | | return existing_session |
| | | |
| | | async def delete_session(self, session_id: str) -> None: |
| | | session = await self.get_session_by_id(session_id) |
| | | if session: |
| | | self.db.delete(session) |
| | | self.db.commit() |
| | | |
| | | async def get_session_list(self, session_id: int, keyword:str="", page: int=1, page_size: int=100) -> any: |
| | | query = self.db.query(ComplexChatSessionModel).filter(ComplexChatSessionModel.session_id==session_id) |
| | | |
| | | if keyword: |
| | | query = query.filter(ComplexChatSessionModel.content.like('%{}%'.format(keyword))) |
| | | total = query.count() |
| | | session_list = query.order_by(ComplexChatSessionModel.create_date.desc()).offset((page-1)*page_size).limit(page_size).all() |
| | | return total, session_list |
| | |
| | | import json |
| | | from typing import Optional, Type, List |
| | | from datetime import datetime |
| | | from typing import List |
| | | |
| | | from pydantic import BaseModel |
| | | from sqlalchemy import Column, Integer, String, BigInteger, ForeignKey, DateTime, Text |
| | | from sqlalchemy.orm import Session |
| | | |
| | | from app.config.const import Dialog_STATSU_DELETE |
| | | from app.models.base_model import Base |
| | | from app.utils.common import current_time |
| | | |
| | | class MindmapRequest(BaseModel): |
| | | messageId: str |
| | | query:str |
| | | |
| | | |
| | | class ChatData(BaseModel): |
| | | sessionId: Optional[str] = "" |
| | | |
| | | class Config: |
| | | extra = 'allow' # 允许其他动态字段 |
| | |
| | | |
| | | |
| | | |
| | | def to_dict(self): |
| | | res = {"files": [], "inputs": {}} |
| | | if hasattr(self, 'files'): |
| | | res['files'] = self.files |
| | | if hasattr(self, 'inputs'): |
| | | res['inputs'] = self.inputs |
| | | return res |
| | | |
| | | |
| | | |
| | | |
| | | class ChatSessionDao: |
| | | def __init__(self, db: Session): |
| | | self.db = db |
| | |
| | | import os.path |
| | | import os.path |
| | | import re |
| | | import uuid |
| | | import base64 |
| | |
| | | if app_dialog: |
| | | dialog.name = app_dialog["name"] |
| | | dialog.description = app_dialog["description"] |
| | | dialog.kb_ids = app_dialog["kb_ids"] |
| | | dialog.update_date = datetime.now() |
| | | db.add(dialog) |
| | | db.commit() |
| | |
| | | import json |
| | | |
| | | import fitz |
| | | import io |
| | | from docx import Document |
| | | from dashscope import get_tokenizer # dashscope版本 >= 1.14.0 |
| | | |
| | | from app.models import ComplexChatSessionDao |
| | | from app.service.auth import decode_access_token |
| | | |
| | | |
| | |
| | | '.docx'): |
| | | text = await read_word(file) |
| | | |
| | | return await get_str_token(text) |
| | | return await get_str_token(text) |
| | | |
| | | |
| | | async def service_chat_message(db, message_id: str): |
| | | message = await ComplexChatSessionDao(db).get_session_by_id(message_id) |
| | | content = "" |
| | | title = "" |
| | | if message: |
| | | content = message.content |
| | | title= json.loads(message.query).get("query") |
| | | return title, content |
| | | |
| | | |
| | | async def generate_word_document(title, content): |
| | | doc = Document() |
| | | # 添加标题 |
| | | doc.add_heading(title, level=1) |
| | | |
| | | # 将内容按段落分割并写入文档 |
| | | for paragraph in content.split('\n'): |
| | | # print("--------------:", paragraph) |
| | | doc.add_paragraph(paragraph) |
| | | |
| | | return doc |
| | |
| | | |
| | | from sqlalchemy import or_ |
| | | |
| | | from app.models import KnowledgeModel, group_knowledge_table |
| | | from app.models import KnowledgeModel, group_knowledge_table, KnowledgeUserModel |
| | | from app.models.user_model import UserModel |
| | | from Log import logger |
| | | from app.task.fetch_agent import get_one_from_ragflow_knowledge |
| | |
| | | query = db.query(KnowledgeModel).filter(KnowledgeModel.knowledge_type==knowledge) |
| | | if user.permission != "admin": |
| | | klg_list = [j.id for i in user.groups for j in i.knowledges] |
| | | for i in db.query(KnowledgeUserModel).filter(KnowledgeUserModel.user_id == user_id, KnowledgeUserModel.status == 1).all(): |
| | | if i.kb_id not in klg_list: |
| | | klg_list.append(i.kb_id) |
| | | query = query.filter(or_(KnowledgeModel.id.in_(klg_list), KnowledgeModel.tenant_id == str(user_id))) |
| | | |
| | | if location: |
| | | query = query.filter(or_(KnowledgeModel.permission == "team", KnowledgeModel.tenant_id == str(user_id))) |
| | | if location: |
| | | query = query.filter(or_(KnowledgeModel.permission == "team", KnowledgeModel.tenant_id == str(user_id))) |
| | | |
| | | if keyword: |
| | | query = query.filter(KnowledgeModel.name.like('%{}%'.format(keyword))) |
| | | total = query.count() |
| | | if page_size: |
| | | query = query.order_by(KnowledgeModel.update_date.desc()).limit(page_size).offset((page_index - 1) * page_size) |
| | | return {"total": total, "rows": [kld.to_json() for kld in query.all()]} |
| | | return {"total": total, "rows": [kld.to_json(str(user_id) if user.permission != "admin" else "admin") for kld in query.all()]} |
| | | |
| | | |
| | | async def create_knowledge_service(db, klg_id, name, description, icon, klg_type, user_id): |
| | | try: |
| | | dialog_model = KnowledgeModel(id=klg_id,name=name, description=description,icon=icon, knowledge_type=klg_type, tenant_id=user_id,update_date=datetime.now(),create_date=datetime.now()) |
| | | db.add(dialog_model) |
| | | kb_user = KnowledgeUserModel(kb_id=klg_id, user_id=user_id, status=1, update_date=datetime.now(), |
| | | create_date=datetime.now()) |
| | | db.add(kb_user) |
| | | db.commit() |
| | | db.refresh(dialog_model) |
| | | except Exception as e: |
| | |
| | | return False |
| | | return True |
| | | |
| | | |
| | | |
| | | async def get_knowledge_users_service(db, kb_id, user_id, page, page_size, member): |
| | | kb_user_list = [] |
| | | user_ids = [] |
| | | kb_info = db.query(KnowledgeModel).filter(KnowledgeModel.id == kb_id).first() |
| | | query = db.query(KnowledgeUserModel).filter(KnowledgeUserModel.kb_id == kb_id) |
| | | if member: |
| | | query = query.filter(KnowledgeUserModel.user_id != user_id) |
| | | total = query.count() |
| | | |
| | | for kld in query.limit(page_size).offset((page - 1) * page_size).all(): |
| | | user_ids.append(kld.user_id) |
| | | print(kb_info.tenant_id) |
| | | kb_user_list.append(kld.to_json(kb_info.tenant_id)) |
| | | user = {i.id: i.username for i in db.query(UserModel).filter(UserModel.id.in_(user_ids)).all()} |
| | | for kld in kb_user_list: |
| | | kld["username"] = user.get(kld["user_id"], "") |
| | | return {"total": total, "rows": kb_user_list} |
| | | |
| | | |
| | | async def set_knowledge_owner_service(db, kb_id, user_id, u_id): |
| | | try: |
| | | db.query(KnowledgeModel).filter_by(id=kb_id).update({"tenant_id": str(user_id), "update_date": datetime.now()}) |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | | db.rollback() |
| | | return False |
| | | return True |
| | | |
| | | |
| | | async def add_knowledge_user_service(db, kb_id, user_id): |
| | | try: |
| | | |
| | | kb_user = KnowledgeUserModel(kb_id=kb_id, user_id=user_id, status=1, update_date=datetime.now(), |
| | | create_date=datetime.now()) |
| | | db.add(kb_user) |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | | db.rollback() |
| | | return False |
| | | return True |
New file |
| | |
| | | -----BEGIN PUBLIC KEY----- |
| | | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8Jak4kGIkOE2kyI0oTcb |
| | | w3yk7OfZ78g1RGvxKlYbKWz93Prxi1pvywXHOnrL/IYDCaNFOybFy5aMbqqvqXOx |
| | | 0LBCqwmB9F07AiEysmhH5m5OxlS9XsxGZb1WeRmobRbge3Hxl59DmUKvD/7Gdsre |
| | | JnDeSWxeaS/zIqLVUsvV3301B08biIywMAKamBQyuJNTPK1ir8iy6peSLPi022zk |
| | | Nl+Rm4ToOrF00oqwB8z5BOTdDcJW/eFlieOyTnWSAFBTIXAB9uqZSjn37kyLKYDh |
| | | yVqB71T/wQvMRip4PPFpCE4UCGGhLHHsKPhtCgxHj6YqE7vUCuGBXP/aagzpWC/H |
| | | ywIDAQAB |
| | | -----END PUBLIC KEY----- |
| | |
| | | import os |
| | | import shutil |
| | | import uuid |
| | | from datetime import datetime |
| | | |
| | | import yaml |
| | | from fastapi import UploadFile |
| | | |
| | | from datetime import datetime |
| | | from fastapi import UploadFile |
| | | from Log import logger |
| | | from app.api import pwd_context |
| | | from app.config.const import SYSTEM_ID, ENV_CONF_PATH, APP_STATIC_PATH |
| | | from app.config.const import SYSTEM_ID, ENV_CONF_PATH, APP_STATIC_PATH, APP_SERVICE_PATH, SYSTEM_STATUS_ON |
| | | from app.models.system import SystemDataModel |
| | | from cryptography.hazmat.primitives import serialization |
| | | from cryptography.hazmat.primitives.asymmetric import padding |
| | | from cryptography.hazmat.primitives import hashes |
| | | import base64 |
| | | import json |
| | | |
| | | from app.utils.common import get_machine_id |
| | | |
| | | |
| | | async def services_get_system_data(db): |
| | |
| | | with open(os.path.join(ENV_CONF_PATH, "system.yaml"), 'r', encoding='utf-8') as file: |
| | | # 加载JSON数据 |
| | | config = yaml.safe_load(file) |
| | | system = SystemDataModel(id=SYSTEM_ID, title=config["smart_system"]["title"], desc=config["smart_system"]["desc"]) |
| | | system = SystemDataModel(id=SYSTEM_ID, title=config["smart_system"]["title"], desc=config["smart_system"]["desc"], version=config["smart_system"]["version"]) |
| | | db.add(system) |
| | | db.commit() |
| | | db.refresh(system) |
| | |
| | | except Exception as e: |
| | | logger.error(f"保存失败: {str(e)}") |
| | | return "" |
| | | |
| | | |
| | | async def services_update_system_license(db, license_code): |
| | | try: |
| | | with open(os.path.join(APP_SERVICE_PATH, "pom/public_key.pem"), "rb") as f: |
| | | public_key = serialization.load_pem_public_key(f.read()) |
| | | license_data, signature = base64.b64decode(license_code).split(b"-----", 1) |
| | | # print(license_data) |
| | | public_key.verify( |
| | | signature, |
| | | license_data, |
| | | padding.PSS( |
| | | mgf=padding.MGF1(hashes.SHA256()), |
| | | salt_length=padding.PSS.MAX_LENGTH |
| | | ), |
| | | hashes.SHA256() |
| | | ) |
| | | license_dict = json.loads(license_data.decode('utf-8')) |
| | | # print(license_dict) |
| | | expiration_date = datetime.fromisoformat(license_dict['expiration_date']) |
| | | if expiration_date < datetime.now(): |
| | | return "授权码已过期" |
| | | system = db.query(SystemDataModel).filter_by(id=SYSTEM_ID).first() |
| | | if license_dict['machine_id'] != get_machine_id() or system.machine_id != license_dict['machine_id']: |
| | | return "授权码无效" |
| | | system.license_code = license_code |
| | | system.expired_at = expiration_date |
| | | system.status = SYSTEM_STATUS_ON |
| | | system.updated_at = datetime.now() |
| | | # db.query(SystemDataModel).filter_by(id=SYSTEM_ID).update({"license_code": license_code, "expired_at": expiration_date, "status": 1, "updated_at": datetime.now()}) |
| | | db.commit() |
| | | return "" |
| | | except Exception as e: |
| | | return f"验证失败: {str(e)}" |
| | |
| | | from datetime import datetime |
| | | from app.api import pwd_context |
| | | from app.config.const import RAGFLOW, BISHENG, DIFY, USER_STATSU_DELETE, ROLE_STATUS_ON, DEPT_STATUS_ON, \ |
| | | Dialog_STATSU_ON |
| | | Dialog_STATSU_ON, USER_STATSU_ON |
| | | from app.models import RoleModel, GroupModel, AgentType, role_resource_table, DialogModel, OrganizationModel, \ |
| | | ResourceModel |
| | | from app.models.menu_model import WebMenuModel, MenuCapacityModel |
| | |
| | | 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"), MenuCapacityModel.chat_type).outerjoin( |
| | | MenuCapacityModel, WebMenuModel.id == MenuCapacityModel.menu_id).outerjoin( |
| | | DialogModel, MenuCapacityModel.capacity_id == DialogModel.id).filter(DialogModel.status=="1").all() |
| | | DialogModel, MenuCapacityModel.capacity_id == DialogModel.id).filter(DialogModel.status==USER_STATSU_ON).all() |
| | | |
| | | for menu in menu_list: |
| | | menu_dict[menu.id] = menu_dict.get(menu.id, []) + [menu] |
| | |
| | | import json |
| | | |
| | | from Log import logger |
| | | # from Log import logger |
| | | from app.models.v2.session_model import ChatData |
| | | from app.service.v2.app_driver.chat_base import ChatBase |
| | |
| | | |
| | | async def chat_completions(self, url, data, headers): |
| | | complete_response = "" |
| | | # print(data) |
| | | async for line in self.http_stream(url, data, headers): |
| | | # logger.error(line) |
| | | if line.startswith("data:"): |
| | |
| | | yield json_data |
| | | |
| | | except json.JSONDecodeError as e: |
| | | # logger.info("Invalid JSON data------------------") |
| | | print(e) |
| | | logger.info("Invalid JSON data------------------") |
| | | # print(e) |
| | | |
| | | @staticmethod |
| | | async def request_data(query: str, conversation_id: str, user:str, chat_data: ChatData) -> dict: |
| | |
| | | "files": files |
| | | } |
| | | |
| | | @staticmethod |
| | | async def complex_request_data(query: str, conversation_id: str, user: str, files: list=None, inputs: dict=None) -> dict: |
| | | if not files: |
| | | files = [] |
| | | if not inputs: |
| | | inputs = {} |
| | | return { |
| | | "inputs": inputs, |
| | | "query": query, |
| | | "response_mode": "streaming", |
| | | "conversation_id": conversation_id, |
| | | "user": user, |
| | | "files": files |
| | | } |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | async def aa(): |
| | |
| | | yield json_data |
| | | |
| | | except json.JSONDecodeError as e: |
| | | # print(e) |
| | | # print(complete_response) |
| | | logger.info("Invalid JSON data------------------") |
| | | # print(e) |
| | | |
| | |
| | | "session_id": session_id |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | @staticmethod |
| | | async def complex_request_data(question, dataset_ids, session_id=""): |
| | | return { |
| | | "question": question, |
| | | "stream": True, |
| | | "session_id": session_id, |
| | | "kb_ids": dataset_ids |
| | | } |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | |
| | | import asyncio |
| | | import io |
| | | import json |
| | | import time |
| | | import uuid |
| | | |
| | | import fitz |
| | | from fastapi import HTTPException |
| | | from sqlalchemy import or_ |
| | | |
| | | from Log import logger |
| | | from app.config.agent_base_url import RG_CHAT_DIALOG, DF_CHAT_AGENT, DF_CHAT_PARAMETERS, RG_CHAT_SESSIONS, \ |
| | | DF_CHAT_WORKFLOW, DF_UPLOAD_FILE, RG_ORIGINAL_URL |
| | | from app.config.config import settings |
| | | from app.config.const import * |
| | | from app.models import DialogModel, ApiTokenModel, UserTokenModel |
| | | from app.models import DialogModel, ApiTokenModel, UserTokenModel, ComplexChatSessionDao, ChatDataRequest, \ |
| | | ComplexChatDao, KnowledgeModel, UserModel, KnowledgeUserModel |
| | | from app.models.v2.session_model import ChatSessionDao, ChatData |
| | | from app.service.v2.app_driver.chat_agent import ChatAgent |
| | | from app.service.v2.app_driver.chat_data import ChatBaseApply |
| | |
| | | |
| | | |
| | | async def add_session_log(db, session_id: str, question: str, chat_id: str, user_id, event_type: str, |
| | | conversation_id: str, agent_type): |
| | | conversation_id: str, agent_type, query: dict=None): |
| | | try: |
| | | session = await ChatSessionDao(db).update_or_insert_by_id( |
| | | session_id=session_id, |
| | |
| | | agent_id=chat_id, |
| | | agent_type=agent_type, |
| | | tenant_id=user_id, |
| | | message={"role": "user", "content": question}, |
| | | message={"role": "user", "content": question, "query": query}, |
| | | conversation_id=conversation_id, |
| | | event_type=event_type |
| | | ) |
| | |
| | | logger.error(e) |
| | | return None |
| | | |
| | | |
| | | async def get_app_token(db, app_id): |
| | | app_token = db.query(UserTokenModel).filter_by(id=app_id).first() |
| | | if app_token: |
| | | return app_token.access_token |
| | | return "" |
| | | |
| | | |
| | | |
| | | async def get_chat_token(db, app_id): |
| | |
| | | logger.error(e) |
| | | |
| | | |
| | | |
| | | async def get_chat_info(db, chat_id: str): |
| | | return db.query(DialogModel).filter_by(id=chat_id, status=Dialog_STATSU_ON).first() |
| | | |
| | |
| | | return ChatAgent(), url |
| | | |
| | | |
| | | async def service_chat_dialog(db, chat_id: str, question: str, session_id: str, user_id, mode: str): |
| | | |
| | | async def get_user_kb(db, user_id: int, kb_ids: list) -> list: |
| | | res = [] |
| | | user = db.query(UserModel).filter(UserModel.id == user_id).first() |
| | | if user is None: |
| | | return res |
| | | query = db.query(KnowledgeModel) |
| | | if user.permission != "admin": |
| | | klg_list = [j.id for i in user.groups for j in i.knowledges] |
| | | for i in db.query(KnowledgeUserModel).filter(KnowledgeUserModel.user_id == user_id, KnowledgeUserModel.status == 1).all(): |
| | | if i.kb_id not in klg_list: |
| | | klg_list.append(i.kb_id) |
| | | query = query.filter(or_(KnowledgeModel.id.in_(klg_list), KnowledgeModel.tenant_id == str(user_id))) |
| | | kb_list= query.all() |
| | | for kb in kb_list: |
| | | if kb.id in kb_ids: |
| | | if kb.permission == "team": |
| | | res.append(kb.id) |
| | | elif kb.tenant_id == str(user_id): |
| | | res.append(kb.id) |
| | | return res |
| | | else: |
| | | return kb_ids |
| | | |
| | | |
| | | async def service_chat_dialog(db, chat_id: str, question: str, session_id: str, user_id: int, mode: str, kb_ids: list): |
| | | conversation_id = "" |
| | | token = await get_chat_token(db, rg_api_token) |
| | | url = settings.fwr_base_url + RG_CHAT_DIALOG.format(chat_id) |
| | | kb_id = await get_user_kb(db, user_id, kb_ids) |
| | | if not kb_id: |
| | | yield "data: " + json.dumps({"message": smart_message_error, |
| | | "error": "\n**ERROR**: The agent has no knowledge base to work with!", "status": http_400}, |
| | | ensure_ascii=False) + "\n\n" |
| | | return |
| | | chat = ChatDialog() |
| | | session = await add_session_log(db, session_id, question, chat_id, user_id, mode, session_id, 1) |
| | | session = await add_session_log(db, session_id, question, chat_id, user_id, mode, session_id, RG_TYPE) |
| | | if session: |
| | | conversation_id = session.conversation_id |
| | | message = {"role": "assistant", "answer": "", "reference": {}} |
| | | try: |
| | | async for ans in chat.chat_completions(url, await chat.request_data(question, conversation_id), |
| | | async for ans in chat.chat_completions(url, await chat.complex_request_data(question, kb_id, conversation_id), |
| | | await chat.get_headers(token)): |
| | | data = {} |
| | | error = "" |
| | |
| | | message["role"] = "assistant" |
| | | await update_session_log(db, session_id, message, conversation_id) |
| | | |
| | | |
| | | async def data_process(data): |
| | | if isinstance(data, str): |
| | | return data.replace("dify", "smart") |
| | |
| | | if hasattr(chat_data, "query"): |
| | | query = chat_data.query |
| | | else: |
| | | query = "start new workflow" |
| | | session = await add_session_log(db, session_id,query if query else "start new conversation", chat_id, user_id, mode, conversation_id, 3) |
| | | query = "start new conversation" |
| | | session = await add_session_log(db, session_id, query if query else "start new conversation", chat_id, user_id, |
| | | mode, conversation_id, DF_TYPE, chat_data.to_dict()) |
| | | if session: |
| | | conversation_id = session.conversation_id |
| | | try: |
| | |
| | | [workflow_started, node_started, node_finished].index(ans.get("event"))] |
| | | elif ans.get("event") == workflow_finished: |
| | | data = ans.get("data", {}) |
| | | answer_workflow = data.get("outputs", {}).get("output") |
| | | answer_workflow = data.get("outputs", {}).get("output", data.get("outputs", {}).get("answer")) |
| | | download_url = data.get("outputs", {}).get("download_url") |
| | | event = smart_workflow_finished |
| | | if data.get("status") == "failed": |
| | |
| | | except: |
| | | ... |
| | | finally: |
| | | await update_session_log(db, session_id, {"role": "assistant", "answer": answer_event or answer_agent or answer_workflow or error, |
| | | "download_url":download_url, |
| | | await update_session_log(db, session_id, {"role": "assistant", |
| | | "answer": answer_event or answer_agent or answer_workflow or error, |
| | | "download_url": download_url, |
| | | "node_list": node_list, "task_id": task_id, "id": message_id, |
| | | "error": error}, conversation_id) |
| | | |
| | | |
| | | |
| | | |
| | | async def service_chat_basic(db, chat_id: str, chat_data: ChatData, session_id: str, user_id, mode: str): |
| | | ... |
| | | |
| | | if chat_id == basic_report_talk: |
| | | complex_chat = await ComplexChatDao(db).get_complex_chat_by_mode(chat_data.report_mode) |
| | | if complex_chat: |
| | | ... |
| | | |
| | | |
| | | |
| | | async def service_chat_parameters(db, chat_id, user_id): |
| | |
| | | if not chat_info: |
| | | return {} |
| | | return chat_info.parameters |
| | | |
| | | |
| | | async def service_chat_sessions(db, chat_id, name): |
| | | token = await get_chat_token(db, rg_api_token) |
| | |
| | | page=current, |
| | | page_size=page_size |
| | | ) |
| | | return json.dumps({"total":total, "rows": [session.to_dict() for session in session_list]}) |
| | | |
| | | return json.dumps({"total": total, "rows": [session.to_dict() for session in session_list]}) |
| | | |
| | | |
| | | async def service_chat_session_log(db, session_id): |
| | | session_log = await ChatSessionDao(db).get_session_by_id(session_id) |
| | | return json.dumps(session_log.log_to_json()) |
| | | if not session_log: |
| | | return {} |
| | | log_info =session_log.log_to_json() |
| | | if session_log.event_type == complex_chat: |
| | | |
| | | total, message_list = await ComplexChatSessionDao(db).get_session_list(session_id) |
| | | log_info["message"] = [message.log_to_json() for message in message_list[::-1]] |
| | | |
| | | return json.dumps(log_info) |
| | | |
| | | |
| | | async def service_chat_upload(db, chat_id, file, user_id): |
| | |
| | | tokens = tokenizer.encode(input_str) |
| | | return len(tokens) |
| | | |
| | | |
| | | async def read_pdf(pdf_stream): |
| | | text = "" |
| | | with fitz.open(stream=pdf_stream, filetype="pdf") as pdf_document: |
| | |
| | | |
| | | return text |
| | | |
| | | |
| | | async def read_file(file, filename, content_type): |
| | | text = "" |
| | | if content_type == "application/pdf" or filename.endswith('.pdf'): |
| | |
| | | |
| | | |
| | | async def service_chunk_retrieval(query, knowledge_id, top_k, similarity_threshold, api_key): |
| | | print(query) |
| | | # print(query) |
| | | |
| | | try: |
| | | request_data = json.loads(query) |
| | |
| | | "question": request_data.get("query", ""), |
| | | "dataset_ids": request_data.get("dataset_ids", []), |
| | | "page_size": top_k, |
| | | "similarity_threshold": similarity_threshold |
| | | "similarity_threshold": similarity_threshold if similarity_threshold else 0.2 |
| | | } |
| | | except json.JSONDecodeError as e: |
| | | fixed_json = query.replace("'", '"') |
| | |
| | | "question": request_data.get("query", ""), |
| | | "dataset_ids": request_data.get("dataset_ids", []), |
| | | "page_size": top_k, |
| | | "similarity_threshold": similarity_threshold |
| | | "similarity_threshold": similarity_threshold if similarity_threshold else 0.2 |
| | | } |
| | | except Exception: |
| | | payload = { |
| | | "question":query, |
| | | "dataset_ids":[knowledge_id], |
| | | "question": query, |
| | | "dataset_ids": [knowledge_id], |
| | | "page_size": top_k, |
| | | "similarity_threshold": similarity_threshold |
| | | "similarity_threshold": similarity_threshold if similarity_threshold else 0.2 |
| | | } |
| | | # print(payload) |
| | | url = settings.fwr_base_url + RG_ORIGINAL_URL |
| | | chat = ChatBaseApply() |
| | | response = await chat.chat_post(url, payload, await chat.get_headers(api_key)) |
| | |
| | | "title": chunk.get("document_keyword", "Unknown Document"), |
| | | "metadata": {"document_id": chunk["document_id"], |
| | | "path": f"{settings.fwr_base_url}/document/{chunk['document_id']}?ext={chunk.get('document_keyword').split('.')[-1]}&prefix=document", |
| | | 'highlight': chunk.get("highlight") , "image_id": chunk.get("image_id"), "positions": chunk.get("positions"),} |
| | | 'highlight': chunk.get("highlight"), "image_id": chunk.get("image_id"), |
| | | "positions": chunk.get("positions"), } |
| | | } |
| | | for chunk in response.get("data", {}).get("chunks", []) |
| | | ] |
| | | # print(len(records)) |
| | | # print(records) |
| | | return records |
| | | |
| | | |
| | | async def service_base_chunk_retrieval(query, knowledge_id, top_k, similarity_threshold, api_key): |
| | | # request_data = json.loads(query) |
| | |
| | | return records |
| | | |
| | | |
| | | async def add_complex_log(db, message_id, chat_id, session_id, chat_mode, query, user_id, mode, agent_type, message_type, conversation_id="", node_data=None, query_data=None): |
| | | if not node_data: |
| | | node_data = [] |
| | | if not query_data: |
| | | query_data = {} |
| | | # print(node_data) |
| | | # print("--------------------------------------------------------") |
| | | # print(query_data) |
| | | try: |
| | | complex_log = ComplexChatSessionDao(db) |
| | | if not conversation_id: |
| | | session = await complex_log.get_session_by_session_id(session_id, chat_id) |
| | | if session: |
| | | conversation_id = session.conversation_id |
| | | await complex_log.create_session(message_id, |
| | | chat_id=chat_id, |
| | | session_id=session_id, |
| | | chat_mode=chat_mode, |
| | | message_type=message_type, |
| | | content=query, |
| | | event_type=mode, |
| | | tenant_id=user_id, |
| | | conversation_id=conversation_id, |
| | | node_data=json.dumps(node_data), |
| | | query=json.dumps(query_data), |
| | | agent_type=agent_type) |
| | | return conversation_id, True |
| | | |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return conversation_id, False |
| | | |
| | | async def add_query_files(db, message_id): |
| | | query = {} |
| | | complex_log = await ComplexChatSessionDao(db).get_session_by_id(message_id) |
| | | if complex_log: |
| | | query = json.loads(complex_log.query) |
| | | return query.get("files", []) |
| | | |
| | | async def service_complex_chat(db, chat_id, mode, user_id, chat_request: ChatDataRequest): |
| | | answer_event = "" |
| | | answer_agent = "" |
| | | answer_dialog = "" |
| | | answer_workflow = "" |
| | | download_url = "" |
| | | message_id = "" |
| | | task_id = "" |
| | | error = "" |
| | | node_list = [] |
| | | reference= {} |
| | | conversation_id = "" |
| | | query_data = chat_request.to_dict() |
| | | new_message_id = str(uuid.uuid4()) |
| | | inputs = {"is_deep": chat_request.isDeep} |
| | | files = chat_request.files |
| | | if chat_request.chatMode == complex_content_optimization_chat: |
| | | inputs["type"] = chat_request.optimizeType |
| | | elif chat_request.chatMode == complex_dialog_chat: |
| | | if not files and chat_request.parentId: |
| | | files = await add_query_files(db, chat_request.parentId) |
| | | if chat_request.chatMode != complex_content_optimization_chat: |
| | | await add_session_log(db, chat_request.sessionId, chat_request.query if chat_request.query else "未命名会话", chat_id, user_id, |
| | | mode, "", DF_TYPE) |
| | | conversation_id, message = await add_complex_log(db, new_message_id, chat_id, chat_request.sessionId, chat_request.chatMode, chat_request.query, user_id, mode, DF_TYPE, 1, query_data=query_data) |
| | | if not message: |
| | | yield "data: " + json.dumps({"message": smart_message_error, |
| | | "error": "\n**ERROR**: 创建会话失败!", "status": http_500}, |
| | | ensure_ascii=False) + "\n\n" |
| | | return |
| | | |
| | | query_data["parentId"] = new_message_id |
| | | try: |
| | | if chat_request.chatMode == complex_knowledge_chat or chat_request.chatMode == complex_knowledge_chat_deep: |
| | | if not conversation_id: |
| | | session = await service_chat_sessions(db, chat_id, chat_request.query) |
| | | # print(session) |
| | | if not session or session.get("code") != 0: |
| | | yield "data: " + json.dumps( |
| | | {"message": smart_message_error, "error": "\n**ERROR**: chat agent error", "status": http_500}) |
| | | return |
| | | conversation_id = session.get("data", {}).get("id") |
| | | token = await get_chat_token(db, rg_api_token) |
| | | url = settings.fwr_base_url + RG_CHAT_DIALOG.format(chat_id) |
| | | chat = ChatDialog() |
| | | try: |
| | | async for ans in chat.chat_completions(url, await chat.complex_request_data(chat_request.query, chat_request.knowledgeId, conversation_id), |
| | | await chat.get_headers(token)): |
| | | data = {} |
| | | error = "" |
| | | status = http_200 |
| | | if ans.get("code", None) == 102: |
| | | error = ans.get("message", "error!") |
| | | status = http_400 |
| | | event = smart_message_error |
| | | else: |
| | | if isinstance(ans.get("data"), bool) and ans.get("data") is True: |
| | | event = smart_message_end |
| | | else: |
| | | data = ans.get("data", {}) |
| | | # conversation_id = data.get("session_id", "") |
| | | if "session_id" in data: |
| | | del data["session_id"] |
| | | data["prompt"] = "" |
| | | if not message_id: |
| | | message_id = data.get("id", "") |
| | | answer_dialog = data.get("answer", "") |
| | | reference = data.get("reference", {}) |
| | | event = smart_message_cover |
| | | message_str = "data: " + json.dumps( |
| | | {"event": event, "data": data, "error": error, "status": status, "message_id":message_id, |
| | | "parent_id": new_message_id, |
| | | "session_id": chat_request.sessionId}, |
| | | ensure_ascii=False) + "\n\n" |
| | | for i in range(0, len(message_str), max_chunk_size): |
| | | chunk = message_str[i:i + max_chunk_size] |
| | | # print(chunk) |
| | | yield chunk # 发送分块消息 |
| | | except Exception as e: |
| | | |
| | | logger.error(e) |
| | | try: |
| | | yield "data: " + json.dumps({"message": smart_message_error, |
| | | "error": "\n**ERROR**: " + str(e), "status": http_500}, |
| | | ensure_ascii=False) + "\n\n" |
| | | except: |
| | | ... |
| | | else: |
| | | token = await get_chat_token(db, chat_id) |
| | | chat, url = await get_chat_object(mode) |
| | | async for ans in chat.chat_completions(url, |
| | | await chat.complex_request_data(chat_request.query, conversation_id, str(user_id), files=files, inputs=inputs), |
| | | await chat.get_headers(token)): |
| | | # print(ans) |
| | | data = {} |
| | | status = http_200 |
| | | conversation_id = ans.get("conversation_id") |
| | | task_id = ans.get("task_id") |
| | | if ans.get("event") == message_error: |
| | | error = ans.get("message", "参数异常!") |
| | | status = http_400 |
| | | event = smart_message_error |
| | | elif ans.get("event") == message_agent: |
| | | data = {"answer": ans.get("answer", ""), "id": ans.get("message_id", "")} |
| | | answer_agent += ans.get("answer", "") |
| | | message_id = ans.get("message_id", "") |
| | | event = smart_message_stream |
| | | elif ans.get("event") == message_event: |
| | | data = {"answer": ans.get("answer", ""), "id": ans.get("message_id", "")} |
| | | answer_event += ans.get("answer", "") |
| | | message_id = ans.get("message_id", "") |
| | | event = smart_message_stream |
| | | elif ans.get("event") == message_file: |
| | | data = {"url": ans.get("url", ""), "id": ans.get("id", ""), |
| | | "type": ans.get("type", "")} |
| | | files.append(data) |
| | | event = smart_message_file |
| | | elif ans.get("event") in [workflow_started, node_started, node_finished]: |
| | | data = ans.get("data", {}) |
| | | data["inputs"] = await data_process(data.get("inputs", {})) |
| | | data["outputs"] = await data_process(data.get("outputs", {})) |
| | | data["files"] = await data_process(data.get("files", [])) |
| | | data["process_data"] = "" |
| | | if data.get("status") == "failed": |
| | | status = http_500 |
| | | error = data.get("error", "") |
| | | node_list.append(ans) |
| | | event = [smart_workflow_started, smart_node_started, smart_node_finished][ |
| | | [workflow_started, node_started, node_finished].index(ans.get("event"))] |
| | | elif ans.get("event") == workflow_finished: |
| | | data = ans.get("data", {}) |
| | | answer_workflow = data.get("outputs", {}).get("output", data.get("outputs", {}).get("answer")) |
| | | download_url = data.get("outputs", {}).get("download_url") |
| | | event = smart_workflow_finished |
| | | if data.get("status") == "failed": |
| | | status = http_500 |
| | | error = data.get("error", "") |
| | | node_list.append(ans) |
| | | |
| | | elif ans.get("event") == message_end: |
| | | event = smart_message_end |
| | | else: |
| | | continue |
| | | |
| | | yield "data: " + json.dumps( |
| | | {"event": event, "data": data, "error": error, "status": status, "task_id": task_id, "message_id":message_id, |
| | | "parent_id": new_message_id, |
| | | "session_id": chat_request.sessionId}, |
| | | ensure_ascii=False) + "\n\n" |
| | | |
| | | except Exception as e: |
| | | logger.error(e) |
| | | try: |
| | | yield "data: " + json.dumps({"message": smart_message_error, |
| | | "error": "\n**ERROR**: " + str(e), "status": http_500}, |
| | | ensure_ascii=False) + "\n\n" |
| | | except: |
| | | ... |
| | | finally: |
| | | # await update_session_log(db, session_id, {"role": "assistant", |
| | | # "answer": answer_event or answer_agent or answer_workflow or error, |
| | | # "download_url": download_url, |
| | | # "node_list": node_list, "task_id": task_id, "id": message_id, |
| | | # "error": error}, conversation_id) |
| | | if message_id: |
| | | await add_complex_log(db, message_id, chat_id, chat_request.sessionId, chat_request.chatMode, answer_event or answer_agent or answer_workflow or answer_dialog or error, user_id, mode, DF_TYPE, 2, conversation_id, node_data=node_list or reference, query_data=query_data) |
| | | |
| | | async def service_complex_upload(db, chat_id, file, user_id): |
| | | files = [] |
| | | token = await get_chat_token(db, chat_id) |
| | | if not token: |
| | | return files |
| | | url = settings.dify_base_url + DF_UPLOAD_FILE |
| | | chat = ChatBaseApply() |
| | | for f in file: |
| | | try: |
| | | file_content = await f.read() |
| | | file_upload = await chat.chat_upload(url, {"file": (f.filename, file_content)}, {"user": str(user_id)}, |
| | | {'Authorization': f'Bearer {token}'}) |
| | | # try: |
| | | # tokens = await read_file(file_content, f.filename, f.content_type) |
| | | # file_upload["tokens"] = tokens |
| | | # except: |
| | | # ... |
| | | files.append(file_upload) |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return json.dumps(files) if files else "" |
| | | |
| | | if __name__ == "__main__": |
| | | q = json.dumps({"query": "设备", "dataset_ids": ["fc68db52f43111efb94a0242ac120004"]}) |
| | | top_k = 2 |
| | | similarity_threshold = 0.5 |
| | | api_key = "ragflow-Y4MGYwY2JlZjM2YjExZWY4ZWU5MDI0Mm" |
| | | |
| | | |
| | | # a = service_chunk_retrieval(q, top_k, similarity_threshold, api_key) |
| | | # print(a) |
| | | async def a(): |
| | | b = await service_chunk_retrieval(q, top_k, similarity_threshold, api_key) |
| | | print(b) |
| | | asyncio.run(a()) |
| | | |
| | | |
| | | asyncio.run(a()) |
| | |
| | | |
| | | |
| | | from Log import logger |
| | | from app.config.agent_base_url import RG_APP_TOKEN_LIST, RG_APP_NEW_TOKEN |
| | | from app.config.agent_base_url import RG_APP_TOKEN_LIST, RG_APP_NEW_TOKEN, DF_CHAT_API_KEY |
| | | # from app.api import pwd_context |
| | | from app.config.const import DIFY, ENV_CONF_PATH, RAGFLOW, smart_server, chat_server, workflow_server, TMP_DICT, \ |
| | | rg_api_token |
| | | rg_api_token, Dialog_STATSU_ON, SYSTEM_ID |
| | | from app.models import MenuCapacityModel, WebMenuModel, GroupModel, RoleModel, DialogModel, UserModel, UserAppModel, \ |
| | | cipher_suite, UserTokenModel, ApiTokenModel |
| | | cipher_suite, UserTokenModel, ApiTokenModel, ComplexChatModel, SystemDataModel |
| | | from app.service.auth import UserAppDao |
| | | from app.service.bisheng import BishengService |
| | | from app.service.difyService import DifyService |
| | |
| | | from app.service.v2.app_driver.chat_data import ChatBaseApply |
| | | from app.service.v2.app_register import AppRegisterDao |
| | | from app.config.config import settings |
| | | from app.service.v2.chat import get_app_token |
| | | from app.utils.common import get_machine_id |
| | | from app.utils.password_handle import generate_password, password_encrypted, password_decrypted |
| | | |
| | | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") |
| | |
| | | |
| | | async def basic_agent_sync(db): |
| | | agent_list = [] |
| | | complex_list = [] |
| | | with open(os.path.join(ENV_CONF_PATH, "default_agent_conf.json"), 'r', encoding='utf-8') as file: |
| | | # 加载JSON数据 |
| | | agent_dict = json.load(file) |
| | | agent_list = agent_dict.get("basic", []) |
| | | complex_list = agent_dict.get("complex", []) |
| | | user = db.query(UserModel).filter_by(permission="admin").first() |
| | | for agent in agent_list: |
| | | dialog = db.query(DialogModel).filter(DialogModel.id == agent["id"]).first() |
| | |
| | | except Exception as e: |
| | | print(e) |
| | | db.rollback() |
| | | now_complex_list = [] |
| | | for agent in complex_list: |
| | | now_complex_list.append(agent["id"]) |
| | | dialog = db.query(ComplexChatModel).filter(ComplexChatModel.id == agent["id"]).first() |
| | | if dialog: |
| | | try: |
| | | dialog.name = agent["name"] |
| | | dialog.description = agent["description"] |
| | | dialog.icon = agent["icon"] |
| | | dialog.mode = agent["mode"] |
| | | dialog.chat_mode = agent["chat_mode"] |
| | | dialog.status = Dialog_STATSU_ON |
| | | # dialog.parameters = json.dumps(agent["parameters"]) |
| | | db.commit() |
| | | except Exception as e: |
| | | logger.error(e) |
| | | else: |
| | | try: |
| | | dialog = ComplexChatModel(id=agent["id"], name=agent["name"], description=agent["description"], |
| | | icon=agent["icon"], tenant_id=user.id if user else "", dialog_type=agent["dialogType"], mode=agent["mode"],chat_mode = agent["chat_mode"]) |
| | | db.add(dialog) |
| | | db.commit() |
| | | db.refresh(dialog) |
| | | except Exception as e: |
| | | print(e) |
| | | db.rollback() |
| | | |
| | | for i in db.query(ComplexChatModel).filter(ComplexChatModel.status == "1").all(): |
| | | if i.id not in now_complex_list: |
| | | try: |
| | | db.query(ComplexChatModel).filter(ComplexChatModel.id==i.id).update(({"status": "0"})) |
| | | db.commit() |
| | | except: |
| | | ... |
| | | |
| | | |
| | | |
| | | async def user_update_app(userid, db): |
| | |
| | | |
| | | except Exception as e: |
| | | print(e) |
| | | db.rollback() |
| | | db.rollback() |
| | | |
| | | |
| | | |
| | | async def sync_complex_api_token(db): |
| | | token = "" |
| | | try: |
| | | complex_list = db.query(ComplexChatModel).all() |
| | | for i in complex_list: |
| | | user_token = db.query(ApiTokenModel).filter(ApiTokenModel.app_id == i.id).first() |
| | | if not user_token: |
| | | try: |
| | | chat = ChatBaseApply() |
| | | url = settings.dify_base_url + DF_CHAT_API_KEY.format(i.id) |
| | | access_token = await get_app_token(db, workflow_server) |
| | | param = await chat.chat_get(url, {}, await chat.get_headers(access_token)) |
| | | if param and param.get("data"): |
| | | token = param.get("data", [{}])[0].get("token") |
| | | token_id = param.get("data", [{}])[0].get("id") |
| | | # dialog.parameters = json.dumps(param) |
| | | else: |
| | | param = await chat.chat_post(url, {}, await chat.get_headers(access_token)) |
| | | if param: |
| | | token = param.get("token") |
| | | token_id = param.get("id") |
| | | |
| | | if token: |
| | | db.add(ApiTokenModel(id=token_id, app_id=i.id, type="app", token=token)) |
| | | db.commit() |
| | | print("df_api_token: 更新成功!") |
| | | except Exception as e: |
| | | print(e) |
| | | |
| | | |
| | | except Exception as e: |
| | | print(e) |
| | | db.rollback() |
| | | |
| | | |
| | | async def system_license_sync(db): |
| | | with open(os.path.join(ENV_CONF_PATH, "system.yaml") , 'r', encoding='utf-8') as file: |
| | | # 加载JSON数据 |
| | | config = json.load(file) |
| | | try: |
| | | system = db.query(SystemDataModel).filter_by(id=SYSTEM_ID).first() |
| | | if system: |
| | | system.version = config["smart_system"].get("version") |
| | | else: |
| | | system = SystemDataModel(id=SYSTEM_ID, version=config["smart_system"].get("version"), title=config["smart_system"].get("title"), desc=config["smart_system"].get("desc"), machine_id=get_machine_id()) |
| | | db.add(system) |
| | | db.commit() |
| | | except Exception as e: |
| | | print(e) |
| | | db.rollback() |
New file |
| | |
| | | import json |
| | | from Log import logger |
| | | from app.config.agent_base_url import DF_CHAT_AGENT, RG_CHAT_DIALOG |
| | | from app.config.config import settings |
| | | from app.config.const import message_error, message_event, complex_knowledge_chat, rg_api_token, workflow_finished |
| | | from app.models import ComplexChatSessionDao, ChatData |
| | | from app.service.v2.app_driver.chat_agent import ChatAgent |
| | | from app.service.v2.app_driver.chat_dialog import ChatDialog |
| | | from app.service.v2.chat import get_chat_token |
| | | |
| | | |
| | | async def service_chat_mindmap_v1(db, message_id, message, mindmap_chat_id, user_id): |
| | | res = {} |
| | | mindmap_query = "" |
| | | complex_log = ComplexChatSessionDao(db) |
| | | session = await complex_log.get_session_by_id(message_id) |
| | | if session: |
| | | token = await get_chat_token(db, session.chat_id) |
| | | chat = ChatAgent() |
| | | url = settings.dify_base_url + DF_CHAT_AGENT |
| | | if session.mindmap: |
| | | chat_request = json.loads(session.query) |
| | | try: |
| | | async for ans in chat.chat_completions(url, |
| | | await chat.request_data(message, session.conversation_id, |
| | | str(user_id), ChatData(), chat_request.get("files", [])), |
| | | await chat.get_headers(token)): |
| | | if ans.get("event") == message_error: |
| | | return res |
| | | elif ans.get("event") == message_event: |
| | | mindmap_query += ans.get("answer", "") |
| | | else: |
| | | continue |
| | | |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return res |
| | | else: |
| | | mindmap_query = session.content |
| | | |
| | | try: |
| | | mindmap_str = "" |
| | | token = await get_chat_token(db, mindmap_chat_id) |
| | | async for ans in chat.chat_completions(url, |
| | | await chat.request_data(mindmap_query, "", |
| | | str(user_id), ChatData()), |
| | | await chat.get_headers(token)): |
| | | if ans.get("event") == message_error: |
| | | return res |
| | | elif ans.get("event") == message_event: |
| | | mindmap_str += ans.get("answer", "") |
| | | else: |
| | | continue |
| | | |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return res |
| | | mindmap_list = mindmap_str.split("```") |
| | | mindmap_str = mindmap_list[1].lstrip("markdown\n") |
| | | if session.mindmap: |
| | | node_list = await mindmap_to_merge(session.mindmap, mindmap_str, f"- {message}") |
| | | mindmap_str = "\n".join(node_list) |
| | | res["mindmap"] = mindmap_str |
| | | await complex_log.update_mindmap_by_id(message_id, mindmap_str) |
| | | return res |
| | | |
| | | |
| | | async def service_chat_mindmap(db, message_id, message, mindmap_chat_id, user_id): |
| | | res = {} |
| | | mindmap_query = "" |
| | | complex_log = ComplexChatSessionDao(db) |
| | | session = await complex_log.get_session_by_id(message_id) |
| | | if session: |
| | | token = await get_chat_token(db, session.chat_id) |
| | | chat = ChatAgent() |
| | | url = settings.dify_base_url + DF_CHAT_AGENT |
| | | chat_request = json.loads(session.query) |
| | | if session.mindmap: |
| | | inputs = {"is_deep": chat_request.get("isDeep", 1)} |
| | | if session.chat_mode == complex_knowledge_chat: |
| | | token = await get_chat_token(db, rg_api_token) |
| | | # print(token) |
| | | dialog_url = settings.fwr_base_url + RG_CHAT_DIALOG.format(session.chat_id) |
| | | dialog_chat = ChatDialog() |
| | | try: |
| | | async for ans in dialog_chat.chat_completions(dialog_url, await dialog_chat.complex_request_data(f"简要总结:{message}", |
| | | chat_request["knowledgeId"], |
| | | session.conversation_id), |
| | | await dialog_chat.get_headers(token)): |
| | | if ans.get("code", None) == 102: |
| | | return res |
| | | else: |
| | | if isinstance(ans.get("data"), bool) and ans.get("data") is True: |
| | | break |
| | | else: |
| | | data = ans.get("data", {}) |
| | | mindmap_query = data.get("answer", "") |
| | | except Exception as e: |
| | | logger.error(e) |
| | | else: |
| | | try: |
| | | async for ans in chat.chat_completions(url, |
| | | await chat.complex_request_data(message, session.conversation_id, |
| | | str(user_id), files=chat_request.get("files", []), inputs=inputs), |
| | | await chat.get_headers(token)): |
| | | if ans.get("event") == message_error: |
| | | return res |
| | | elif ans.get("event") == workflow_finished: |
| | | mindmap_query = ans.get("data", {}).get("outputs", {}).get("answer", "") |
| | | else: |
| | | continue |
| | | |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return res |
| | | else: |
| | | mindmap_query = session.content |
| | | # print("-----------------", mindmap_query) |
| | | try: |
| | | if chat_request.get("isDeep", 1) == 2: |
| | | mindmap_query = mindmap_query.split("</think>")[-1] |
| | | mindmap_str = "" |
| | | # print("mindmap_query", mindmap_query) |
| | | token = await get_chat_token(db, mindmap_chat_id) |
| | | async for ans in chat.chat_completions(url, |
| | | await chat.complex_request_data(mindmap_query, "", |
| | | str(user_id)), |
| | | await chat.get_headers(token)): |
| | | # print(ans) |
| | | if ans.get("event") == message_error: |
| | | return res |
| | | elif ans.get("event") == message_event: |
| | | mindmap_str += ans.get("answer", "") |
| | | else: |
| | | continue |
| | | |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return res |
| | | # print(mindmap_str) |
| | | if "```json" in mindmap_str: |
| | | mindmap_list = mindmap_str.split("```") |
| | | mindmap_str = mindmap_list[1].lstrip("json") |
| | | mindmap_str = mindmap_str.replace("\n", "") |
| | | if session.mindmap: |
| | | mindmap_str = await mindmap_merge_dict(session.mindmap, mindmap_str, message) |
| | | |
| | | try: |
| | | res_str = await mindmap_join_str(mindmap_str) |
| | | res["mindmap"] = res_str |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return res |
| | | await complex_log.update_mindmap_by_id(message_id, mindmap_str) |
| | | return res |
| | | |
| | | async def mindmap_merge_dict(parent, child, target_node): |
| | | parent_dict = json.loads(parent) |
| | | if child: |
| | | child_dict = json.loads(child) |
| | | def iter_dict(node): |
| | | if "items" not in node: |
| | | if node["title"] == target_node: |
| | | node["items"] = child_dict["items"] |
| | | return |
| | | else: |
| | | for i in node["items"]: |
| | | iter_dict(i) |
| | | iter_dict(parent_dict) |
| | | |
| | | return json.dumps(parent_dict) |
| | | |
| | | |
| | | async def mindmap_join_str(mindmap_json): |
| | | try: |
| | | parent_dict = json.loads(mindmap_json) |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return "" |
| | | def join_node(node, level): |
| | | mindmap_str = "" |
| | | if level <= 2: |
| | | mindmap_str += f"{'#'*level} {node['title']}\n" |
| | | else: |
| | | mindmap_str += f"{' '*(level-3)*2}- {node['title']}\n" |
| | | for i in node.get("items", []): |
| | | mindmap_str += join_node(i, level+1) |
| | | return mindmap_str |
| | | |
| | | return join_node(parent_dict, 1) |
| | | |
| | | async def mindmap_to_merge(parent, child, target_node): |
| | | level = 0 |
| | | index = 0 |
| | | new_node_list = [] |
| | | parent_list= parent.split("\n") |
| | | child_list= child.split("\n") |
| | | child_list[0] = target_node |
| | | for i, node in enumerate(parent_list): |
| | | if node.endswith(target_node): |
| | | level = len(node) - len(target_node) |
| | | index = i |
| | | break |
| | | tmp_level = 0 |
| | | for child in child_list: |
| | | if "#" in child: |
| | | childs = child.split("#") |
| | | tmp_level = len(childs) - 2 |
| | | new_node_list.append(" "*(level+tmp_level)+ "-"+childs[-1]) |
| | | elif len(child) == 0: |
| | | continue |
| | | else: |
| | | new_node_list.append(" "*(level+tmp_level)+child) |
| | | |
| | | return parent_list[:index]+new_node_list+parent_list[index+1:] |
| | | |
| | | |
| | | async def service_message_mindmap_parse(db, message_id, user_id): |
| | | res = {} |
| | | complex_log = ComplexChatSessionDao(db) |
| | | session = await complex_log.get_session_by_id(message_id) |
| | | |
| | | if session.mindmap: |
| | | try: |
| | | res_str = await mindmap_join_str(session.mindmap) |
| | | res["mindmap"] = res_str |
| | | except Exception as e: |
| | | logger.error(e) |
| | | return res |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | a = '{ "title": "全生命周期管理", "items": [ { "title": "设备规划与采购", "items": [ { "title": "需求分析与选型" ,"items": [{"title": "rererer"}, {"title": "trtrtrtrt"}] }, { "title": "供应商选择与合同管理" } ] }, { "title": "设备安装与调试", "items": [ { "title": "安装规范" }, { "title": "调试测试" } ] }, { "title": "设备使用", "items": [ { "title": "操作培训" }, { "title": "操作规程与记录" } ] }, { "title": "设备维护与维修", "items": [ { "title": "定期维护" }, { "title": "故障诊断" }, { "title": "备件管理" } ] }, { "title": "设备更新与改造", "items": [ { "title": "技术评估" }, { "title": "更新计划" }, { "title": "改造方案" } ] }, { "title": "设备报废", "items": [ { "title": "报废评估" }, { "title": "报废处理" } ] }, { "title": "信息化管理", "items": [ { "title": "设备管理系统" }, { "title": "数据分析" }, { "title": "远程监控" } ] }, { "title": "安全管理", "items": [ { "title": "安全培训" }, { "title": "安全检查" }, { "title": "应急预案" } ] }, { "title": "环境保护", "items": [ { "title": "环保设备" }, { "title": "废物处理" }, { "title": "节能减排" } ] }, { "title": "具体实践案例", "items": [ { "title": "高压开关设备润滑脂选用研究" }, { "title": "环保型 C4 混气 GIS 设备运维技术研究" } ] }, { "title": "总结", "items": [ { "title": "提高运营效率和竞争力" } ] } ]}' |
| | | b = mindmap_merge_dict(a, {}, "设备规划与采购") |
| | | print(b) |
| | |
| | | |
| | | from app.config.config import settings |
| | | from app.config.const import RAGFLOW, BISHENG, DIFY, ENV_CONF_PATH, Dialog_STATSU_DELETE, Dialog_STATSU_ON |
| | | from app.models import KnowledgeModel |
| | | from app.models import KnowledgeModel, ComplexChatDao |
| | | from app.models.dialog_model import DialogModel |
| | | from app.models.user_model import UserAppModel |
| | | from app.models.agent_model import AgentModel |
| | |
| | | status = Column(String(1), nullable=False) |
| | | description = Column(String(255), nullable=False) |
| | | tenant_id = Column(String(36), nullable=False) |
| | | kb_ids = Column(String(128), nullable=False) |
| | | |
| | | |
| | | class DfApps(Base): |
| | |
| | | db.close() |
| | | |
| | | |
| | | def get_data_from_ragflow_v2(names: List[str], tenant_id) -> List[Dict]: |
| | | def get_data_from_ragflow_v2(base_db, names: List[str], tenant_id) -> List[Dict]: |
| | | db = SessionRagflow() |
| | | para = { |
| | | "user_input_form": [], |
| | |
| | | } |
| | | } |
| | | try: |
| | | chat_ids = ComplexChatDao(base_db).get_complex_chat_ids() |
| | | # print(chat_ids) |
| | | if names: |
| | | query = db.query(Dialog.id, Dialog.name, Dialog.description, Dialog.status, Dialog.tenant_id) \ |
| | | .filter(Dialog.name.in_(names), Dialog.status == "1") |
| | | else: |
| | | query = db.query(Dialog.id, Dialog.name, Dialog.description, Dialog.status, Dialog.tenant_id).filter( |
| | | query = db.query(Dialog.id, Dialog.name, Dialog.description, Dialog.status, Dialog.tenant_id, Dialog.kb_ids).filter( |
| | | Dialog.status == "1", Dialog.tenant_id == tenant_id) |
| | | |
| | | results = query.all() |
| | | formatted_results = [ |
| | | {"id": row[0], "name": row[1], "description": row[2], "status": "1" if row[3] == "1" else "2", |
| | | "user_id": str(row[4]), "mode": "agent-dialog", "parameters": para} for row in results] |
| | | "user_id": str(row[4]), "mode": "agent-dialog", "parameters": para, "kb_ids": row[5]} for row in results if row[0] not in chat_ids] |
| | | return formatted_results |
| | | finally: |
| | | db.close() |
| | | |
| | | |
| | | def get_data_from_dy_v2(names: List[str]) -> List[Dict]: |
| | | def get_data_from_dy_v2(base_db, names: List[str]) -> List[Dict]: |
| | | db = SessionDify() |
| | | try: |
| | | chat_ids = ComplexChatDao(base_db).get_complex_chat_ids() |
| | | # print(chat_ids) |
| | | if names: |
| | | query = db.query(DfApps.id, DfApps.name, DfApps.description, DfApps.status, DfApps.tenant_id, DfApps.mode) \ |
| | | .filter(DfApps.name.in_(names)) |
| | |
| | | results = query.all() |
| | | formatted_results = [ |
| | | {"id": str(row[0]), "name": row[1], "description": row[2], "status": "1", |
| | | "user_id": str(row[4]), "mode": row[5], "parameters": {}} for row in results] |
| | | "user_id": str(row[4]), "mode": row[5], "parameters": {}} for row in results if str(row[0]) not in chat_ids] |
| | | return formatted_results |
| | | finally: |
| | | db.close() |
| | |
| | | existing_agent.name = row["name"] |
| | | existing_agent.description = row["description"] |
| | | existing_agent.mode = row["mode"] |
| | | existing_agent.kb_ids = row.get("kb_ids", "") |
| | | if existing_agent.status == Dialog_STATSU_DELETE: |
| | | existing_agent.status = Dialog_STATSU_ON |
| | | if row["parameters"]: |
| | | existing_agent.parameters = json.dumps(row["parameters"]) |
| | | else: |
| | | existing = DialogModel(id=row["id"], status=row["status"], name=row["name"], |
| | | description=row["description"], |
| | | description=row["description"], kb_ids=row.get("kb_ids", ""), |
| | | tenant_id=get_rag_user_id(db, row["user_id"], type_dict[dialog_type]), |
| | | dialog_type=dialog_type, mode=row["mode"], parameters=json.dumps(row["parameters"])) |
| | | db.add(existing) |
| | |
| | | for app in app_register: |
| | | try: |
| | | if app["id"] == RAGFLOW: |
| | | ragflow_data = get_data_from_ragflow_v2([], app["name"]) |
| | | ragflow_data = get_data_from_ragflow_v2(db, [], app["name"]) |
| | | if ragflow_data: |
| | | update_ids_in_local_v2(ragflow_data, "1") |
| | | elif app["id"] == DIFY: |
| | | dify_data = get_data_from_dy_v2([]) |
| | | dify_data = get_data_from_dy_v2(db, []) |
| | | if dify_data: |
| | | update_ids_in_local_v2(dify_data, "4") |
| | | except Exception as e: |
| | |
| | | def get_one_from_ragflow_dialog(dialog_id): |
| | | db = SessionRagflow() |
| | | try: |
| | | row = db.query(Dialog.id, Dialog.name, Dialog.description, Dialog.status, Dialog.tenant_id) \ |
| | | row = db.query(Dialog.id, Dialog.name, Dialog.description, Dialog.status, Dialog.tenant_id, Dialog.kb_ids) \ |
| | | .filter(Dialog.id==dialog_id).first() |
| | | return {"id": row[0], "name": row[1], "description": row[2], "status": str(row[3]), |
| | | "user_id": str(row[4])} if row else {} |
| | | "user_id": str(row[4]), "kb_ids": row[5]} if row else {} |
| | | finally: |
| | | db.close() |
| | | |
| | |
| | | async def sync_token_chat(token_id, url, data, is_crypt, ping_url, token): |
| | | db = SessionLocal() |
| | | # pdb = PostgresqlSessionLocal() |
| | | current_time = datetime.now() - timedelta(hours=12) |
| | | current_time = datetime.now() - timedelta(hours=24) |
| | | try: |
| | | user_token = db.query(UserTokenModel).filter(UserTokenModel.id == token_id).first() |
| | | chat = ChatBaseApply() |
New file |
| | |
| | | import asyncio |
| | | import base64 |
| | | import json |
| | | import os |
| | | |
| | | from datetime import datetime |
| | | from cryptography.hazmat.primitives import serialization |
| | | from cryptography.hazmat.primitives.asymmetric import padding |
| | | from cryptography.hazmat.primitives import hashes |
| | | from app.config.const import SYSTEM_ID, SYSTEM_STATUS_EXPIRED, SYSTEM_STATUS_ON, APP_SERVICE_PATH |
| | | from app.models import SystemDataModel |
| | | from app.models.base_model import SessionLocal |
| | | from app.utils.common import get_machine_id |
| | | |
| | | |
| | | async def sync_system_license(): |
| | | print("-------------------------------------------") |
| | | db = SessionLocal() |
| | | try: |
| | | system = db.query(SystemDataModel).filter_by(id=SYSTEM_ID).first() |
| | | if not system: |
| | | return |
| | | machine_id = get_machine_id() |
| | | if system.machine_id: |
| | | if system.machine_id != machine_id: |
| | | system.machine_id = machine_id |
| | | if system.status == SYSTEM_STATUS_ON: |
| | | system.status = SYSTEM_STATUS_EXPIRED |
| | | else: |
| | | if system.status == SYSTEM_STATUS_ON: |
| | | if not system.license_code or system.expired_at < datetime.now(): |
| | | system.status = SYSTEM_STATUS_EXPIRED |
| | | else: |
| | | try: |
| | | with open(os.path.join(APP_SERVICE_PATH, "pom/public_key.pem"), "rb") as f: |
| | | public_key = serialization.load_pem_public_key(f.read()) |
| | | license_data, signature = base64.b64decode(system.license_code).split(b"-----", 1) |
| | | # print(license_data) |
| | | public_key.verify( |
| | | signature, |
| | | license_data, |
| | | padding.PSS( |
| | | mgf=padding.MGF1(hashes.SHA256()), |
| | | salt_length=padding.PSS.MAX_LENGTH |
| | | ), |
| | | hashes.SHA256() |
| | | ) |
| | | license_dict = json.loads(license_data.decode('utf-8')) |
| | | # print(license_dict) |
| | | expiration_date = datetime.fromisoformat(license_dict['expiration_date']) |
| | | system.expired_at = expiration_date |
| | | if expiration_date < datetime.now(): |
| | | system.status = SYSTEM_STATUS_EXPIRED |
| | | except Exception as e: |
| | | print(e) |
| | | system.status = SYSTEM_STATUS_EXPIRED |
| | | else: |
| | | if system.status == SYSTEM_STATUS_ON: |
| | | system.status = SYSTEM_STATUS_EXPIRED |
| | | db.commit() |
| | | except Exception as e: |
| | | print(e) |
| | | finally: |
| | | db.close() |
| | | |
| | | |
| | | def sync_resource(): |
| | | asyncio.run(sync_system_license()) |
New file |
| | |
| | | import pytz |
| | | import platform |
| | | import subprocess |
| | | |
| | | from datetime import datetime |
| | | |
| | | |
| | | def current_time(): |
| | | tz = pytz.timezone('Asia/Shanghai') |
| | | return datetime.now(tz) |
| | | |
| | | |
| | | def get_machine_id(): |
| | | """获取机器的唯一标识""" |
| | | if platform.system() == "Windows": |
| | | # Windows 系统 |
| | | command = "wmic csproduct get UUID" |
| | | process = subprocess.Popen(command.split(), stdout=subprocess.PIPE) |
| | | output, _ = process.communicate() |
| | | machine_id = output.decode().strip().split("\n")[1].strip() |
| | | elif platform.system() == "Darwin": |
| | | # macOS 系统 |
| | | command = "system_profiler SPHardwareDataType | grep 'Hardware UUID' | awk '{print $4}'" |
| | | process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) |
| | | output, _ = process.communicate() |
| | | machine_id = output.decode().strip() |
| | | else: |
| | | # Linux 系统 |
| | | machine_id = open("/etc/machine-id").read().strip() |
| | | # print(machine_id) |
| | | return machine_id |
| | |
| | | from app.api.organization import dept_router |
| | | from app.api.system import system_router |
| | | from app.api.v2.chat import chat_router_v2 |
| | | from app.api.v2.mindmap import mind_map_router |
| | | from app.api.v2.public_api import public_api |
| | | from app.api.report import router as report_router |
| | | from app.api.resource import menu_router |
| | |
| | | sync_resources_from_json |
| | | from app.init_config.init_run_data import sync_default_data |
| | | from app.task.sync_account_token import start_sync_token_task |
| | | from app.task.sync_system import sync_resource |
| | | |
| | | init_db() |
| | | |
| | |
| | | scheduler = BackgroundScheduler() |
| | | scheduler.add_job(sync_agents_v2, 'interval', minutes=60, id="sync_resource_data") |
| | | scheduler.add_job(start_sync_token_task, 'interval', minutes=5, id="sync_token_1") |
| | | scheduler.add_job(sync_resource, 'interval', minutes=5, id="sync_resource_1") |
| | | |
| | | scheduler.start() |
| | | |
| | |
| | | app.include_router(dialog_router, prefix='/api/dialog', tags=["dialog"]) |
| | | app.include_router(canvas_router, prefix='/api/canvas', tags=["canvas"]) |
| | | app.include_router(label_router, prefix='/api/label', tags=["label"]) |
| | | app.include_router(public_api, prefix='/v1/api', tags=["public_api"]) |
| | | app.include_router(public_api, prefix='/v1', tags=["public_api"]) |
| | | app.include_router(chat_router_v2, prefix='/api/v1', tags=["chat1"]) |
| | | app.include_router(system_router, prefix='/api/system', tags=["system"]) |
| | | app.include_router(mind_map_router, prefix='/api/mindmap', tags=["mindmap"]) |
| | | app.mount("/static", StaticFiles(directory="app/images"), name="static") |
| | | |
| | | if __name__ == "__main__": |