diff --git a/AI/WxMini/Start.py b/AI/WxMini/Start.py index a9f3cbe5..7c82a988 100644 --- a/AI/WxMini/Start.py +++ b/AI/WxMini/Start.py @@ -602,24 +602,67 @@ async def generate_upload_params(current_user: dict = Depends(get_current_user)) @app.get("/aichat/recognize_content") -async def web_recognize_content(image_url: str, current_user: dict = Depends(get_current_user)): - logger.info(f"current_user:{current_user['login_name']}") - person_id = current_user['person_id'] - try: - async def generate_stream(): - # 假设 recognize_content 是一个异步生成器,逐条返回识别结果 - async for result in recognize_content(client, app.state.mysql_pool, person_id, image_url): - yield f"{str(result)}" # 使用SSE格式 - # 控制输出速度,间隔0.01秒 - await asyncio.sleep(0.01) +async def web_recognize_content(image_url: str, + #current_user: dict = Depends(get_current_user) + ): + #logger.info(f"current_user:{current_user['login_name']}") + #person_id = current_user['person_id'] + person_id='0F66D9C5-428C-FE03-67EE-E5BEE46CB495' + # 获取图片宽高 + image_width, image_height = getImgWidthHeight(image_url) + + # 调用 AI 模型生成内容(流式输出) + response = await client.chat.completions.create( + model="qwen-vl-plus", + messages=[{"role": "user", "content": [ + {"type": "text", "text": "这是什么"}, + {"type": "image_url", "image_url": {"url": image_url}} + ]}], + stream=True + ) - return StreamingResponse( - generate_stream(), - media_type="text/event-stream", # 使用SSE的media_type - headers={"Cache-Control": "no-cache", "Connection": "keep-alive"} # 禁用缓存,保持连接 - ) - except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + # 定义一个生成器函数,用于逐字返回流式结果 + async def generate_stream(): + summary = "" # 用于存储最终拼接的字符串 + try: + # 逐块处理 AI 返回的内容 + async for chunk in response: + if chunk.choices[0].delta.content: + chunk_content = chunk.choices[0].delta.content + # 逐字返回 + for char in chunk_content: + print(char, end="", flush=True) # 打印到控制台 + yield char.encode("utf-8") # 逐字返回 + summary += char # 拼接字符 + + # 流式传输完成后,记录到数据库 + await save_chat_to_mysql( + app.state.mysql_pool, person_id, f'{image_url}', summary, "", 0, 2, 2, 2, image_width, image_height + ) + + except asyncio.CancelledError: + # 客户端提前断开连接,无需处理 + print("客户端断开连接") + except Exception as e: + error_response = json.dumps({ + "success": False, + "message": f"生成内容失败: {str(e)}" + }) + print(error_response) + yield error_response.encode("utf-8") + + # 使用 StreamingResponse 返回流式结果 + return StreamingResponse( + generate_stream(), + media_type="text/plain; charset=utf-8", # 明确指定字符编码为 UTF-8 + headers={ + "Cache-Control": "no-cache", # 禁用缓存 + "Content-Type": "text/event-stream; charset=utf-8", # 设置内容类型和字符编码 + "Transfer-Encoding": "chunked", + "Connection": "keep-alive", + "X-Accel-Buffering": "no", # 禁用 Nginx 缓冲(如果使用 Nginx) + } + ) @app.get("/aichat/recognize_text") diff --git a/AI/WxMini/Utils/ImageUtil.py b/AI/WxMini/Utils/ImageUtil.py index 915a8d88..7c6b37b6 100644 --- a/AI/WxMini/Utils/ImageUtil.py +++ b/AI/WxMini/Utils/ImageUtil.py @@ -53,36 +53,6 @@ async def recognize_text(client, pool, person_id, image_url): print(f"记录到数据库时出错:{e}") -async def recognize_content(client, pool, person_id, image_url): - """ - 识别图片中的内容,流式输出 - """ - completion = await client.chat.completions.create( - model="qwen-vl-plus", - messages=[{"role": "user", "content": [ - {"type": "text", "text": "这是什么"}, - {"type": "image_url", "image_url": {"url": image_url}} - ]}], - stream=True - ) - full_text = "" # 用于存储最终拼接的字符串 - async for chunk in completion: - if chunk.choices[0].delta.content is not None: - for char in chunk.choices[0].delta.content: - if char != ' ': - yield char # 流式输出字符 - full_text += char # 拼接字符 - # print(char, end='') - time.sleep(0.1) # 控制输出速度 - - # 获取图片宽高 - image_width, image_height = getImgWidthHeight(image_url) - # 记录到数据库 - try: - await save_chat_to_mysql(pool, person_id, f'{image_url}', full_text, "", 0, 2, 2, 2, image_width, image_height) - except Exception as e: - print(f"记录到数据库时出错:{e}") - async def recognize_math(pool, person_id, image_url): client = AsyncOpenAI(