From 657ec149a83cc5c77b4853228696d5257192fc6f Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Tue, 25 Mar 2025 18:22:50 +0800 Subject: [PATCH] 'commit' --- AI/WxMini/Start.py | 45 +++++++----- AI/WxMini/Test/TongJi.py | 67 ------------------ AI/WxMini/Utils/MySQLUtil.py | 50 +++++++++---- .../__pycache__/MySQLUtil.cpython-310.pyc | Bin 3090 -> 5967 bytes AI/WxMini/__pycache__/Start.cpython-310.pyc | Bin 5914 -> 8251 bytes 5 files changed, 65 insertions(+), 97 deletions(-) delete mode 100644 AI/WxMini/Test/TongJi.py diff --git a/AI/WxMini/Start.py b/AI/WxMini/Start.py index 58f9165f..f3ef07ff 100644 --- a/AI/WxMini/Start.py +++ b/AI/WxMini/Start.py @@ -13,7 +13,7 @@ from WxMini.Milvus.Utils.MilvusConnectionPool import * from WxMini.Utils.OssUtil import upload_mp3_to_oss_from_memory from WxMini.Utils.TtsUtil import TTS from WxMini.Utils.MySQLUtil import init_mysql_pool, save_chat_to_mysql, get_chat_log_by_session, update_risk, \ - get_risk_chat_log_page + get_risk_chat_log_page, get_last_chat_log_id from WxMini.Utils.EmbeddingUtil import text_to_embedding # 配置日志 @@ -47,13 +47,26 @@ async def lifespan(app: FastAPI): # 会话结束后,调用检查方法,判断是不是有需要介入的问题出现 async def on_session_end(session_id): - # 获取聊天记录 - result = await get_chat_log_by_session(app.state.mysql_pool, session_id, page=1, page_size=1) + # 获取最后一条聊天记录 + last_id = await get_last_chat_log_id(app.state.mysql_pool, session_id) + if last_id: + # 查询最后一条记录的详细信息 + async with app.state.mysql_pool.acquire() as conn: + async with conn.cursor() as cur: + await cur.execute( + "SELECT user_input, model_response FROM t_chat_log WHERE id = %s", + (last_id,) + ) + last_record = await cur.fetchone() + + if last_record: + # 拼接历史聊天记录 + history = f"问题:{last_record['user_input']}\n回答:{last_record['model_response']}" + else: + history = "无聊天记录" + else: + history = "无聊天记录" - # 拼接历史聊天记录 - history = "" - for row in result['data']: - history = f"{history}\n问题:{row['user_input']}\n回答:{row['model_response']}" # 将历史聊天记录发给大模型,让它帮我分析一下 prompt = ( @@ -225,27 +238,25 @@ async def reply(session_id: str = Form(...), prompt: str = Form(...)): milvus_pool.release_connection(connection) +# 获取聊天记录 + # 获取聊天记录 @app.get("/aichat/get_chat_log") async def get_chat_log( session_id: str, - page: int = Query(default=1, ge=1, description="当前页码"), + page: int = Query(default=None, ge=1, description="当前页码(如果为 None,则默认跳转到最后一页)"), page_size: int = Query(default=10, ge=1, le=100, description="每页记录数") ): """ - 根据 session_id 查询聊天记录,并按 id 降序分页 + 获取指定会话的聊天记录,默认返回最新的记录(最后一页) :param session_id: 用户会话 ID - :param page: 当前页码 + :param page: 当前页码(如果为 None,则默认跳转到最后一页) :param page_size: 每页记录数 :return: 分页数据 """ - try: - result = await get_chat_log_by_session(app.state.mysql_pool, session_id, page, page_size) - return result - except Exception as e: - logger.error(f"查询聊天记录失败: {str(e)}") - raise HTTPException(status_code=500, detail=f"查询聊天记录失败: {str(e)}") - + # 调用 get_chat_log_by_session 方法 + result = await get_chat_log_by_session(app.state.mysql_pool, session_id, page, page_size) + return result @app.get("/aichat/get_risk_page") async def get_risk_page( diff --git a/AI/WxMini/Test/TongJi.py b/AI/WxMini/Test/TongJi.py deleted file mode 100644 index 628714f3..00000000 --- a/AI/WxMini/Test/TongJi.py +++ /dev/null @@ -1,67 +0,0 @@ -import asyncio -from openai import AsyncOpenAI -from WxMini.Milvus.Config.MulvusConfig import * -from WxMini.Utils.MySQLUtil import init_mysql_pool, get_chat_log_by_session - -# 初始化异步 OpenAI 客户端 -client = AsyncOpenAI( - api_key=MODEL_API_KEY, - base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", -) - -async def main(): - # 哪个人员 - session_id = 1 - # 哪一页 - page = 1 - # 一页多少个 - page_size = 100 - - # 初始化 MySQL 连接池 - mysql_pool = await init_mysql_pool() - - # 调用 - result = await get_chat_log_by_session(mysql_pool, session_id, page, page_size) - - # 我只关心 user_input 与 model_response - # 把这些拼接出问题与回答 - history = "" - for row in result['data']: # 注意:result 是一个字典,包含 'data' 字段 - user_input = row['user_input'] - model_response = row['model_response'] - history = f"{history}\n问题:{user_input}\n回答:{model_response}" - - # 将历史聊天记录发给大模型,让它帮我分析一下 - prompt = ( - "我将把用户与AI大模型交流的记录发给你,帮我分析一下这个用户是否存在心理健康方面的问题," - "参考:1、PHQ-9抑郁症筛查量表和2、Beck自杀意念评量表(BSI-CV)。" - "如果没有健康问题请回复: OK;否则回复:NO,换行后再输出是什么问题。" - f"\n\n历史聊天记录:{history}" - ) - - # 调用大模型进行分析 - try: - response = await client.chat.completions.create( - model=MODEL_NAME, - messages=[ - {"role": "system", "content": "你是一个心理健康分析助手,负责分析用户的心理健康状况。"}, - {"role": "user", "content": prompt} - ], - max_tokens=1000 - ) - # 提取大模型的回复 - if response.choices and response.choices[0].message.content: - analysis_result = response.choices[0].message.content.strip() - print("大模型分析结果:") - print(analysis_result) - else: - print("大模型未返回有效结果。") - except Exception as e: - print(f"调用大模型失败: {str(e)}") - - # 关闭连接池 - mysql_pool.close() - await mysql_pool.wait_closed() - -if __name__ == '__main__': - asyncio.run(main()) \ No newline at end of file diff --git a/AI/WxMini/Utils/MySQLUtil.py b/AI/WxMini/Utils/MySQLUtil.py index 3559fd95..b24bd5d6 100644 --- a/AI/WxMini/Utils/MySQLUtil.py +++ b/AI/WxMini/Utils/MySQLUtil.py @@ -44,18 +44,18 @@ async def truncate_chat_log(mysql_pool): # 分页查询聊天记录 -async def get_chat_log_by_session(mysql_pool, session_id, page=1, page_size=10): +async def get_chat_log_by_session(mysql_pool, session_id, page=None, page_size=10): """ - 根据 session_id 查询聊天记录,并按 id 降序分页 + 根据 session_id 查询聊天记录,并按 id 升序分页 + :param mysql_pool: MySQL 连接池 :param session_id: 用户会话 ID - :param page: 当前页码 + :param page: 当前页码(如果为 None,则默认跳转到最后一页) :param page_size: 每页记录数 :return: 分页数据 """ if not mysql_pool: raise ValueError("MySQL 连接池未初始化") - offset = (page - 1) * page_size async with mysql_pool.acquire() as conn: async with conn.cursor() as cur: # 查询总记录数 @@ -65,10 +65,20 @@ async def get_chat_log_by_session(mysql_pool, session_id, page=1, page_size=10): ) total = (await cur.fetchone())[0] - # 查询分页数据,按 id 降序排列 + # 计算总页数 + total_pages = (total + page_size - 1) // page_size + + # 如果未指定页码,则默认跳转到最后一页 + if page is None: + page = total_pages + + # 计算偏移量 + offset = (page - 1) * page_size + + # 查询分页数据,按 id 升序排列 await cur.execute( "SELECT id, session_id, user_input, model_response, audio_url, duration, create_time " - "FROM t_chat_log WHERE session_id = %s ORDER BY id DESC LIMIT %s OFFSET %s", + "FROM t_chat_log WHERE session_id = %s ORDER BY id ASC LIMIT %s OFFSET %s", (session_id, page_size, offset) ) records = await cur.fetchall() @@ -88,26 +98,40 @@ async def get_chat_log_by_session(mysql_pool, session_id, page=1, page_size=10): ] return { - "data": result, + "data": result, # 按 id 升序排列的数据 "total": total, "page": page, - "page_size": page_size + "page_size": page_size, + "total_pages": total_pages } -# 更新为危险的记录 -async def update_risk(mysql_pool, session_id, risk_memo): +# 获取指定会话的最后一条记录的 id +async def get_last_chat_log_id(mysql_pool, session_id): + """ + 获取指定会话的最后一条记录的 id + :param mysql_pool: MySQL 连接池 + :param session_id: 用户会话 ID + :return: 最后一条记录的 id,如果未找到则返回 None + """ async with mysql_pool.acquire() as conn: async with conn.cursor() as cur: - # 1. 获取此人员的最后一条记录 id await cur.execute( "SELECT id FROM t_chat_log WHERE session_id = %s ORDER BY id DESC LIMIT 1", (session_id,) ) result = await cur.fetchone() + return result[0] if result else None + + +# 更新为危险的记录 +async def update_risk(mysql_pool, session_id, risk_memo): + async with mysql_pool.acquire() as conn: + async with conn.cursor() as cur: + # 1. 获取此人员的最后一条记录 id + last_id = await get_last_chat_log_id(mysql_pool, session_id) - if result: - last_id = result[0] + if last_id: # 2. 更新 risk_flag 和 risk_memo await cur.execute( "UPDATE t_chat_log SET risk_flag = 1, risk_memo = %s WHERE id = %s", diff --git a/AI/WxMini/Utils/__pycache__/MySQLUtil.cpython-310.pyc b/AI/WxMini/Utils/__pycache__/MySQLUtil.cpython-310.pyc index 90ecbe7d8e0ab56b4b7d4c9863ec8aa8e019027f..bef1a1937aff4f6df597e10cfd2bfc9b7a169510 100644 GIT binary patch literal 5967 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 diff --git a/AI/WxMini/__pycache__/Start.cpython-310.pyc b/AI/WxMini/__pycache__/Start.cpython-310.pyc index 56a81c811002a8417e5f5a5560437c77717005cf..58368920199a2cc99927df3142bb86698aa6431c 100644 GIT binary patch delta 4100 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 JfuJNm_!|}Q**O3J