From 3b1bf7da6771bd1d6852d3dcc1f906d5ae5c95d1 Mon Sep 17 00:00:00 2001 From: zhaoqingang <zhaoqg0118@163.com> Date: 星期三, 12 三月 2025 13:49:12 +0800 Subject: [PATCH] 增加内容优化 --- app/config/env_conf/default_agent_conf.json | 91 +++++++++++++++ app/service/v2/chat.py | 48 +++++-- app/init_config/init_run_data.py | 12 - app/service/files.py | 28 ++++ app/service/v2/mindmap.py | 1 app/config/const.py | 14 + app/task/sync_account_token.py | 2 app/service/v2/app_driver/chat_agent.py | 5 app/api/files.py | 25 +++ app/service/v2/initialize_data.py | 63 ++++++++++ app/models/v2/chat.py | 35 +++-- 11 files changed, 276 insertions(+), 48 deletions(-) diff --git a/app/api/files.py b/app/api/files.py index 0592b4b..7107025 100644 --- a/app/api/files.py +++ b/app/api/files.py @@ -1,4 +1,5 @@ import io +import time from typing import Optional, List import requests @@ -19,7 +20,7 @@ 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 @@ -242,4 +243,24 @@ break yield data - return StreamingResponse(generate(), media_type="application/octet-stream") \ No newline at end of file + 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") diff --git a/app/config/const.py b/app/config/const.py index a173fe6..9c369f7 100644 --- a/app/config/const.py +++ b/app/config/const.py @@ -1,5 +1,5 @@ -### ----------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" @@ -62,6 +62,7 @@ agent_chat = "agent-chat" base_chat = "chat" basic_chat = "agent-basic" +complex_chat = "complex-chat" ### ------------------------------ @@ -118,5 +119,12 @@ complex_dialog_chat = 1 # 鏂囨。鍜屽熀纭�瀵硅瘽 complex_network_chat = 2 # 鑱旂綉瀵硅瘽 complex_knowledge_chat = 3 # 鐭ヨ瘑搴撳璇� -# complex_deep_chat = 4 -complex_mindmap_chat = 5 \ No newline at end of file +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 # 鎶ュ憡 + +### --------------------------------basic develop agent--------------------------------------------------- +basic_report_talk ="basic_report_talk" \ No newline at end of file diff --git a/app/config/env_conf/default_agent_conf.json b/app/config/env_conf/default_agent_conf.json index b58a3a6..a37e185 100644 --- a/app/config/env_conf/default_agent_conf.json +++ b/app/config/env_conf/default_agent_conf.json @@ -139,5 +139,94 @@ "mode": "agent-basic" } ], - "bs": [] + "complex": [ + { + "id": "c703ad73-faed-4fab-b00c-717766ad71dd", + "name": "鐭ヨ瘑搴撲笓瀹�", + "description": "鐭ヨ瘑搴撲笓瀹�", + "icon": "intellFrame4", + "chat_mode": 3, + "parameters": { + }, + "dialogType": "4", + "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" + } + ] } \ No newline at end of file diff --git a/app/init_config/init_run_data.py b/app/init_config/init_run_data.py index db095fb..c0ff67e 100644 --- a/app/init_config/init_run_data.py +++ b/app/init_config/init_run_data.py @@ -1,6 +1,6 @@ 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 from app.task.sync_account_token import sync_token @@ -10,17 +10,15 @@ 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鐧诲綍 except Exception as e: print(e) finally: db.close() - # await default_role_sync(db) # 椤甸潰璧勬簮閰嶇疆淇℃伅 - # await default_role_sync(db) # 榛樿鐨勮鑹茶祫婧� diff --git a/app/models/v2/chat.py b/app/models/v2/chat.py index 86d7ea4..e41edcf 100644 --- a/app/models/v2/chat.py +++ b/app/models/v2/chat.py @@ -26,6 +26,7 @@ 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] = [] @@ -38,6 +39,7 @@ "knowledgeId": self.knowledgeId, "files": self.files, "isDeep": self.isDeep, + "optimizeType": self.optimizeType, } @@ -173,15 +175,19 @@ } def log_to_json(self): - return { - 'id': self.id, - 'name': self.name, - 'agent_type': self.agent_type, - 'chat_id': self.agent_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"), - 'message': json.loads(self.message) - } + if self.message_type == 1: + return { + 'id': self.id, + 'role': "user", + 'content': self.content, + } + else: + return { + 'id': self.id, + 'role': "assistant", + 'answer': self.content, + 'node_list': json.loads(self.node_data) if self.node_data else [], + } class ComplexChatSessionDao: @@ -238,12 +244,11 @@ self.db.delete(session) self.db.commit() - async def get_session_list(self, user_id: int, agent_id: str, keyword:str, page: int, page_size: int) -> any: - query = self.db.query(ComplexChatSessionModel).filter(ComplexChatSessionModel.tenant_id==user_id) - if agent_id: - query = query.filter(ComplexChatSessionModel.agent_id==agent_id) + 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.name.like('%{}%'.format(keyword))) + query = query.filter(ComplexChatSessionModel.content.like('%{}%'.format(keyword))) total = query.count() - session_list = query.order_by(ComplexChatSessionModel.update_date.desc()).offset((page-1)*page_size).limit(page_size).all() + session_list = query.order_by(ComplexChatSessionModel.create_date.desc()).offset((page-1)*page_size).limit(page_size).all() return total, session_list \ No newline at end of file diff --git a/app/service/files.py b/app/service/files.py index ad0e93e..69f21ed 100644 --- a/app/service/files.py +++ b/app/service/files.py @@ -1,8 +1,11 @@ +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 @@ -52,4 +55,27 @@ '.docx'): text = await read_word(file) - return await get_str_token(text) \ No newline at end of file + 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 \ No newline at end of file diff --git a/app/service/v2/app_driver/chat_agent.py b/app/service/v2/app_driver/chat_agent.py index 5fa0bfa..a9d1790 100644 --- a/app/service/v2/app_driver/chat_agent.py +++ b/app/service/v2/app_driver/chat_agent.py @@ -1,5 +1,6 @@ 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 @@ -26,8 +27,8 @@ 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: diff --git a/app/service/v2/chat.py b/app/service/v2/chat.py index 83ea02a..0942681 100644 --- a/app/service/v2/chat.py +++ b/app/service/v2/chat.py @@ -1,6 +1,7 @@ import asyncio import io import json +import time import uuid import fitz @@ -11,7 +12,8 @@ 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, ComplexChatSessionDao, ChatDataRequest +from app.models import DialogModel, ApiTokenModel, UserTokenModel, ComplexChatSessionDao, ChatDataRequest, \ + ComplexChatDao 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 @@ -90,7 +92,7 @@ token = await get_chat_token(db, rg_api_token) url = settings.fwr_base_url + RG_CHAT_DIALOG.format(chat_id) 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": {}} @@ -173,7 +175,7 @@ else: 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, 3) + mode, conversation_id, DF_TYPE) if session: conversation_id = session.conversation_id try: @@ -251,8 +253,15 @@ "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): @@ -285,7 +294,15 @@ 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 session_log else {}) + 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): @@ -470,23 +487,28 @@ error = "" files = [] node_list = [] + conversation_id = "" token = await get_chat_token(db, chat_id) chat, url = await get_chat_object(mode) - conversation_id, message = await add_complex_log(db, str(uuid.uuid4()),chat_id, chat_request.sessionId, chat_request.chatMode, chat_request.query, user_id, mode, DF_TYPE, 1, query_data=chat_request.to_dict()) - if not message: - yield "data: " + json.dumps({"message": smart_message_error, - "error": "\n**ERROR**: 鍒涘缓浼氳瘽澶辫触锛�", "status": http_500}, - ensure_ascii=False) + "\n\n" - return + 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, str(uuid.uuid4()),chat_id, chat_request.sessionId, chat_request.chatMode, chat_request.query, user_id, mode, DF_TYPE, 1, query_data=chat_request.to_dict()) + if not message: + yield "data: " + json.dumps({"message": smart_message_error, + "error": "\n**ERROR**: 鍒涘缓浼氳瘽澶辫触锛�", "status": http_500}, + ensure_ascii=False) + "\n\n" + return inputs = {"is_deep": chat_request.isDeep} if chat_request.chatMode == complex_knowledge_chat: inputs["query_json"] = json.dumps({"query": chat_request.query, "dataset_ids": chat_request.knowledgeId}) - + elif chat_request.chatMode == complex_content_optimization_chat: + inputs["type"] = chat_request.optimizeType try: async for ans in chat.chat_completions(url, await chat.complex_request_data(chat_request.query, conversation_id, str(user_id), files=chat_request.files, inputs=inputs), await chat.get_headers(token)): - print(ans) + # print(ans) data = {} status = http_200 conversation_id = ans.get("conversation_id") diff --git a/app/service/v2/initialize_data.py b/app/service/v2/initialize_data.py index 1f05cab..eacdefa 100644 --- a/app/service/v2/initialize_data.py +++ b/app/service/v2/initialize_data.py @@ -7,12 +7,12 @@ 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 from app.models import MenuCapacityModel, WebMenuModel, GroupModel, RoleModel, DialogModel, UserModel, UserAppModel, \ - cipher_suite, UserTokenModel, ApiTokenModel + cipher_suite, UserTokenModel, ApiTokenModel, ComplexChatModel from app.service.auth import UserAppDao from app.service.bisheng import BishengService from app.service.difyService import DifyService @@ -21,6 +21,7 @@ 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.password_handle import generate_password, password_encrypted, password_decrypted pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @@ -131,10 +132,12 @@ 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() @@ -152,6 +155,30 @@ try: dialog = DialogModel(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"],parameters = json.dumps(agent["parameters"])) + db.add(dialog) + db.commit() + db.refresh(dialog) + except Exception as e: + print(e) + db.rollback() + + for agent in complex_list: + 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.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) @@ -353,4 +380,36 @@ except Exception as e: print(e) + 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: + 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) db.rollback() \ No newline at end of file diff --git a/app/service/v2/mindmap.py b/app/service/v2/mindmap.py index 79620f5..f6e576c 100644 --- a/app/service/v2/mindmap.py +++ b/app/service/v2/mindmap.py @@ -75,7 +75,6 @@ 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: inputs["query_json"] = json.dumps( diff --git a/app/task/sync_account_token.py b/app/task/sync_account_token.py index 55e0082..55b1893 100644 --- a/app/task/sync_account_token.py +++ b/app/task/sync_account_token.py @@ -38,7 +38,7 @@ 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() -- Gitblit v1.8.0