针对微信小程序的后台经过5天测试,具备一定的稳定性,提交版本用于保存

This commit is contained in:
qcloud
2025-07-27 21:37:28 +08:00
parent 44cb7c0dca
commit e6644a5262
18 changed files with 3147 additions and 376 deletions

View File

@@ -31,7 +31,7 @@ from api.utils.api_utils import get_result
from api.utils.file_utils import get_project_base_directory from api.utils.file_utils import get_project_base_directory
from rag.utils.minio_conn import RAGFlowMinio from rag.utils.minio_conn import RAGFlowMinio
import logging import logging
import base64, gzip import base64, gzip,json
import io, re, json import io, re, json
from io import BytesIO from io import BytesIO
import queue,time,uuid,os,array import queue,time,uuid,os,array
@@ -135,13 +135,13 @@ def upload_file(tenant_id,mesum_id):
mesum_id_str = str(mesum_id) mesum_id_str = str(mesum_id)
labels_with_id = get_labels_with_id(mesum_id) labels_with_id = get_labels_with_id(mesum_id)
antique_labels = ','.join([item['label'] for item in labels_with_id]) antique_labels = ';'.join([item['label'] for item in labels_with_id]) # 使用分号分隔
joined_string = antique_labels joined_string = antique_labels
antiques_selected = f"{joined_string}" antiques_selected = f"{joined_string}"
#logging.info(f"mesumid={mesum_id} {joined_string}") #logging.info(f"mesumid={mesum_id} {joined_string}")
prompt1 = (f"你是一名图片识别和理解助手" prompt1= (f"你是一名图片识别和理解助手"
f"任务是先识别图片中文字,然后理解文字中包含的内容,分析哪一项可以作为识别出文字的标题," f"任务是先识别图片中文字,然后理解文字中包含的内容,分析哪一项可以作为识别出文字的标题,"
f"你的回答有3个结果第一个结果匹配出的结果,JSON键值为antique" f"你的回答有3个结果第一个结果匹配出的结果,JSON键值为antique"
f"从下面的候选项:{antiques_selected}进行匹配,每一个候选项中间以';'分割,如果没有任何匹配则结果为'',以免误触发讲解,匹配成功则输出匹配出的内容" f"从下面的候选项:{antiques_selected}进行匹配,每一个候选项中间以';'分割,如果没有任何匹配则结果为'',以免误触发讲解,匹配成功则输出匹配出的内容"
@@ -151,25 +151,29 @@ def upload_file(tenant_id,mesum_id):
f"原始数据的键值为text输出是1个完整的JSON数据不要有多余的前置和后置内容确保前端能正确解析出JSON数据") f"原始数据的键值为text输出是1个完整的JSON数据不要有多余的前置和后置内容确保前端能正确解析出JSON数据")
prompt = ( prompt = (
f"作为图片识别和理解助手,您的任务是:" f"作为博物馆展品识别专家,您的任务是:"
f"\n1. 图片基本上就是展品标题、历史人物或者历史事件" f"\n1. 识别图片中的文字内容,重点关注展品标题(通常是最大/最显眼的文字)"
f"\n2. 精确识别图片中的文字内容,理解文字语义,重点分析字体较大的文字" f"\n2. 从以下候选标题中匹配最佳项:{antiques_selected}"
f"\n3. 识别出的文字包含标题或者接近于标题的文字" f"\n3. 匹配规则:"
f"\n4. 从以下候选标题中选择最佳匹配项:" f"\n - 优先匹配完整标题(如'铜踵饰残片'匹配'铜踵饰残片'"
f"\n {antiques_selected}" f"\n - 其次匹配关键词(如'刻辞卜骨'可匹配'刻辞卜骨'"
f"\n\n### 输出要求:" f"\n - 允许部分匹配(如'铜器'匹配'青铜器'"
f"\n- 以严格JSON格式输出包含3个字段" f"\n - 忽略拼音、英文和次要描述文字"
f"\n • `antique`: 匹配的标题(多个用英文分号';'分割最多匹配3个无匹配则空字符串" f"\n - 如果近似,不好区分,则输出数组供前端选择,如:青铜车䡇匹配青铜车䡇;青铜车軛一对"
f"\n • `text`: 识别出的完整文字" f"\n4. 输出要求:"
f"\n • `match_score`: 整体匹配度(0-1的浮点数)1=完全匹配" f"\n - 匹配结果最多不超过5个"
f"\n\n### 匹配规则:" f"\n - 用英文分号';'分隔多个匹配项"
f"\n1. 语义匹配优先于字面匹配" f"\n\n输出严格JSON格式"
f"\n2. 考虑同义词、近义词和描述性匹配" f"\n{'{'}"
f"\n3. 允许部分匹配(如'青铜酒器'匹配'青铜器'" f"\n \"antique\": \"匹配结果(多个用分号分隔)\","
f"\n4. 若无明确匹配项,`antique`返回空字符串" f"\n \"text\": \"识别出的完整文字\","
f"\n\n### 重要:" f"\n \"match_score\": 整体匹配度(0-1)"
f"\n- 输出必须是可直接解析的JSON无任何前置/后置文本" f"\n{'}'}"
f"\n- 匹配度评分需客观反映文本与候选标题的相似度" f"\n\n示例:"
f"\n候选标题:青铜车䡇;玉虎;甲骨文;刻辞卜骨"
f"\n识别文字:『青铜车䡇』商代..."
f"\n正确输出:"
f"\n{'{'}\"antique\": \"青铜车轼\", \"text\": \"青铜车轼 (yue)...\", \"match_score\": 0.95{'}'}"
) )
file = request.files['file'] file = request.files['file']
@@ -212,7 +216,7 @@ def upload_file(tenant_id,mesum_id):
] ]
) )
"""
client = OpenAI( client = OpenAI(
api_key="sk-a47a3fb5f4a94f66bbaf713779101c75", api_key="sk-a47a3fb5f4a94f66bbaf713779101c75",
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
@@ -238,20 +242,58 @@ def upload_file(tenant_id,mesum_id):
}, },
], ],
) )
"""
vl_model = "doubao-1-5-thinking-vision-pro-250428"
client = OpenAI(
api_key="1e04d30a-0c56-4dbd-b873-53f26649c64f",
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
response = client.chat.completions.create(
# 指定您创建的方舟推理接入点 ID此处已帮您修改为您的推理接入点 ID
model=vl_model,
messages=[
{
"role": "system",
"content": [{"type": "text", "text": prompt}],
},
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{img_base}"
},
}
],
}
],
)
message = response.choices[0].message message = response.choices[0].message
parsed_json_res = parse_markdown_json(message.content)
parsed_json_data = {"antique": "", "text": "", "match_score": 0} parsed_json_data = {"antique": "", "text": "", "match_score": 0}
matchedArray = [] matchedArray = []
try:
if isinstance(message.content, str):
parsed_json_res = parse_markdown_json(message.content) # 优先识别带有markdown格式
if parsed_json_res.get('success') is False: # 如果识别失败再识别普通json格式(字符串)
parsed_json_data = json.loads(message.content)
parsed_json_res['success'] = True
parsed_json_res['data'] = parsed_json_data
except Exception as e:
pass
#logging.info(f"识别完成 {message.content} {parsed_json_data} ")
if parsed_json_res.get('success') is True: if parsed_json_res.get('success') is True:
parsed_json_data = parsed_json_res.get('data') parsed_json_data = parsed_json_res.get('data')
matchedAntiqueArray = parsed_json_data.get('antique').split(';') # 识别出的文物的数组,中间以';'分割,可能有多个 matchedAntiqueArray = parsed_json_data.get('antique').split(';') # 识别出的文物的数组,中间以';'分割,可能有多个
if len(matchedAntiqueArray) ==1: # 只有一个匹配项,直接返回 if len(matchedAntiqueArray) ==1: # 只有一个匹配项,直接返回
logging.info(f"识别完成 得到1个{parsed_json_data.get('antique')} {labels_with_id} ")
for item in labels_with_id: for item in labels_with_id:
if item['label'] == parsed_json_data.get('antique'): if item['label'] == parsed_json_data.get('antique'):
parsed_json_data['id'] = item.get('id') parsed_json_data['id'] = item.get('id')
else: # 有多个匹配项,需要进行多个匹配 else: # 有多个匹配项,需要进行多个匹配
for label in matchedAntiqueArray: for label in matchedAntiqueArray[:5]:
antique= {'label':label} antique= {'label':label}
for item in labels_with_id: for item in labels_with_id:
if item['label'] == label: if item['label'] == label:

View File

@@ -115,6 +115,7 @@ def update(tenant_id, chat_id, session_id):
@token_required @token_required
def completion(tenant_id, chat_id): # chat_id 和 别的文件中的dialog_id 应该是一个意思? cyx 2025-01-25 def completion(tenant_id, chat_id): # chat_id 和 别的文件中的dialog_id 应该是一个意思? cyx 2025-01-25
req = request.json req = request.json
logging.info(f"/chats/{chat_id}/completions--0 req={req}") # cyx
if not req.get("session_id"): # session_id 和 别的文件中的conversation_id 应该是一个意思? cyx 2025-01-25 if not req.get("session_id"): # session_id 和 别的文件中的conversation_id 应该是一个意思? cyx 2025-01-25
conv = { conv = {
"id": get_uuid(), "id": get_uuid(),

View File

@@ -1042,6 +1042,7 @@ class MesumOverview(DataBaseModel):
index=False) index=False)
free = IntegerField(default=0, index=False) free = IntegerField(default=0, index=False)
hotspot_rank = IntegerField(default=50, index=False)
def __str__(self): def __str__(self):
return self.name return self.name

View File

@@ -34,5 +34,5 @@ COPY app ./app
EXPOSE 9580 EXPOSE 9580
# 启动命令 # 启动命令
CMD ["python3", "-m", "app.main"] #CMD ["python3", "-m", "app.main"]
# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "9480"] CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "9580"]

View File

@@ -1,15 +1,142 @@
INFO: Started server process [2877053] INFO: Started server process [175422]
INFO: Waiting for application startup. INFO: Waiting for application startup.
16:01:53.789 - INFO - 监控服务已启动 14:09:53.459 - INFO - 监控服务已启动
INFO: Application startup complete. INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:9580 (Press CTRL+C to quit) INFO: Uvicorn running on http://0.0.0.0:9580 (Press CTRL+C to quit)
WARNING: Invalid HTTP request received. 14:10:04.372 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTM2NzkxMzB9.k-lALo9ulLGnu5O9qZALEp45F2loDnfdBZ09C9vglIw', 'balance': 0, 'status': 1, 'last_login_time': 1753074330, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1753074330, 'update_date': datetime.datetime(2025, 7, 21, 13, 5, 30)}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ASR & Monitor Service Start ASR & Monitor Service Start
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
INFO: 91.196.152.109:33535 - "GET / HTTP/1.1" 404 Not Found tts_service路由器正在启动...
INFO: 220.196.160.51:32110 - "GET / HTTP/1.1" 404 Not Found INFO: 43.140.60.33:0 - "GET /auth/verify HTTP/1.1" 200 OK
INFO: 180.101.245.250:54556 - "GET / HTTP/1.1" 404 Not Found INFO: 43.144.107.28:0 - "POST /payment/get_user_museum_subscriptions HTTP/1.1" 200 OK
INFO: 220.196.160.75:44896 - "GET / HTTP/1.1" 404 Not Found 14:10:08.416 - INFO - Creating TTS request: {'text': '提梁三足铜盉5.2749通梁高22.5厘米高19.5厘米口径4.8厘米腹径11.0厘米,平谷区南独乐河公社刘家河大队出土,首都博物馆藏。铜盉为长颈,圆鼓腹,三足,有一绦状提梁,肩部附一圆柱形流。提梁盉在郑州和湖北盘龙城的二里岗期铜器中均未见。安阳殷墟妇好墓中出有一件, 其 制与此盉有所不同,花纹亦比较精美。 此盉可能是与殷墟二期提梁盉的过渡形态。', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'model_name': 'sambert-zhichu-v1@Tongyi-Qianwen', 'sample_rate': 8000, 'stream_format': 'mp3'}
INFO: 91.196.152.210:40043 - "GET /favicon.ico HTTP/1.1" 404 Not Found INFO: 43.140.60.33:0 - "POST /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts?device_id=17528308107741998517 HTTP/1.1" 200 OK
WARNING: Invalid HTTP request received. INFO: ('1.13.185.116', 40190) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/9dd9cff1-093c-4b9f-a3d6-a701fdcf7ad3" [accepted]
14:10:09.160 - INFO - 新连接建立: b9980686-a10d-4082-9d13-bf1260ea95b7
14:10:09.160 - INFO - 已经启动 start tts task {audio_stream_id}
14:10:09.161 - INFO - ---begin--init QwenTTS-- mp3 8000 sambert-zhichu-v1@Tongyi-Qianwen
14:10:09.161 - INFO - Qwen text_tts_call <speak>提梁三足铜盉5.2749通梁高22.5厘米高19.5厘米口径4.8厘米腹径11.0厘米,平谷区南独乐河公社刘家河大队出土,首都博物馆藏。铜盉为长颈,圆鼓腹,三足,有一绦状提梁,肩部附一圆柱形流。提梁盉在郑州和湖北盘龙城的二里岗期铜器中均未见。安阳殷墟妇好墓中出有一件, 其 制与此盉有所不同,花纹亦比较精美。 此盉可能是与殷墟二期提梁盉的过渡形态。</speak>
INFO: connection open
INFO: connection closed
14:10:11.978 - INFO - 发送时检测到断开连接: b9980686-a10d-4082-9d13-bf1260ea95b7,
14:10:11.978 - WARNING - Send failed, connection closed: b9980686-a10d-4082-9d13-bf1260ea95b7
14:10:11.978 - WARNING - 尝试向不存在的连接发送数据: b9980686-a10d-4082-9d13-bf1260ea95b7
14:10:12.091 - INFO - --data_handler on_complete
14:10:12.091 - INFO - --tts task event set error = None
14:10:12.091 - INFO - UnifiedTTSEngine _run_tts_sync finally
INFO: ('1.13.185.116', 40194) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/0770c61f-3a83-4c68-9ac8-e304405c0eef" [accepted]
14:10:12.371 - INFO - 新连接建立: eb86ddd7-224b-45a9-a0d0-081c52b5b17e
INFO: connection open
14:10:12.493 - INFO - 代理文本流: completions_url=http://127.0.0.1:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions {'question': '请介绍提梁三足铜盉', 'stream': True, 'tts_model': 'sambert-zhichu-v1@Tongyi-Qianwen', 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'tts_disable': True}
14:10:15.632 - INFO - HTTP Request: POST http://127.0.0.1:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions "HTTP/1.1 200 OK"
14:10:15.632 - INFO - 响应状态: HTTP 200
14:10:15.632 - INFO - ---begin--init QwenTTS-- mp3 8000 sambert-zhichu-v1@Tongyi-Qianwen
14:10:15.632 - INFO - --StreamSessionManager create_session last_active=1753078215.632958
14:10:15.633 - INFO - 开始处理SSE流
14:10:15.633 - INFO - --proxy_aichat_text_stream 发送audio_stream_url
14:10:15.683 - INFO - Qwen text_tts_call <speak>提梁三足铜盉是商代文物,</speak>
INFO: ('1.13.185.116', 54072) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/06af3ad0-024e-4e6d-a3ea-71373ff05280" [accepted]
14:10:16.294 - INFO - 新连接建立: be24c0be-8a30-460c-99ff-747745d2c522
INFO: connection open
14:10:17.144 - INFO - Qwen text_tts_call <speak>通梁高22.5厘米高19.5厘米口径4.8厘米腹径11.0厘米。出土于平谷区南独乐河公社刘家河大队,现藏于首都博物馆。</speak>
14:10:19.318 - INFO - Qwen text_tts_call <speak>其特征为长颈圆鼓腹三足,有一绦状提梁,肩部附一圆柱形流。</speak>
14:10:20.791 - INFO - SSE流处理完成事件数: 12
INFO: connection closed
14:10:21.059 - INFO - Qwen text_tts_call <speak>此盉在郑州和湖北盘龙城的二里岗期铜器中未见,与安阳殷墟妇好墓出土的提梁盉有所不同,花纹较精美,可能是殷墟二期提梁盉的过渡形态。</speak>
INFO: connection closed
14:10:21.394 - INFO - 发送时检测到断开连接: be24c0be-8a30-460c-99ff-747745d2c522,
14:10:21.394 - INFO - --- proxy AiChatTts audio_data_size=94212
14:10:23.002 - INFO - 清理资源: 0会话
14:10:24.462 - INFO - Creating TTS request: {'text': '玉牛首通长3.7厘米宽2.7厘米,河南省信阳市罗山县天湖墓地出土,信阳博物馆藏。\n', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'model_name': 'sambert-zhichu-v1@Tongyi-Qianwen', 'sample_rate': 8000, 'stream_format': 'mp3'}
INFO: 43.140.60.44:0 - "POST /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts?device_id=17528308107741998517 HTTP/1.1" 200 OK
INFO: ('1.13.185.116', 33942) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/5286022d-3c15-4aa0-a11d-6af6823c89ae" [accepted]
14:10:24.737 - INFO - 新连接建立: 0f8be756-1592-4fe2-958e-074819796722
14:10:24.737 - INFO - 已经启动 start tts task {audio_stream_id}
14:10:24.737 - INFO - ---begin--init QwenTTS-- mp3 8000 sambert-zhichu-v1@Tongyi-Qianwen
14:10:24.737 - INFO - Qwen text_tts_call <speak>玉牛首通长3.7厘米宽2.7厘米,河南省信阳市罗山县天湖墓地出土,信阳博物馆藏。</speak>
INFO: connection open
14:10:25.734 - INFO - --data_handler on_complete
14:10:25.734 - INFO - --tts task event set error = None
14:10:25.734 - INFO - UnifiedTTSEngine _run_tts_sync finally
INFO: connection closed
INFO: ('1.13.185.116', 33958) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/d3fe9c0c-45ab-4821-98b4-ef28ad6b7264" [accepted]
14:10:30.629 - INFO - 新连接建立: 64ac60ed-59ee-4d39-ab67-c92a583aacd6
INFO: connection open
14:10:30.690 - INFO - 代理文本流: completions_url=http://127.0.0.1:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions {'question': '请介绍玉牛首', 'stream': True, 'tts_model': 'sambert-zhichu-v1@Tongyi-Qianwen', 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'tts_disable': True}
14:10:33.444 - INFO - HTTP Request: POST http://127.0.0.1:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions "HTTP/1.1 200 OK"
14:10:33.444 - INFO - 响应状态: HTTP 200
14:10:33.444 - INFO - ---begin--init QwenTTS-- mp3 8000 sambert-zhichu-v1@Tongyi-Qianwen
14:10:33.445 - INFO - --StreamSessionManager create_session last_active=1753078233.4450512
14:10:33.445 - INFO - 开始处理SSE流
14:10:33.446 - INFO - --proxy_aichat_text_stream 发送audio_stream_url
14:10:33.495 - INFO - Qwen text_tts_call <speak>玉牛首是商代的一件玉器通长3.7厘米,</speak>
INFO: ('1.13.185.116', 33966) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/dfa471ae-b608-48f8-aa38-f3da27aa9da9" [accepted]
14:10:33.919 - INFO - 新连接建立: 2cb47c8b-842c-47a8-b221-42caf74e089a
INFO: connection open
14:10:35.077 - INFO - Qwen text_tts_call <speak>宽2.7厘米,出土于河南省信阳市罗山县天湖墓地,现藏于信阳博物馆。</speak>
14:10:36.370 - INFO - SSE流处理完成事件数: 9
INFO: connection closed
14:10:36.911 - INFO - Qwen text_tts_call <speak>这件玉器以牛首为题材,雕刻精细,形象生动,反映了商代玉器工艺的高超水平。玉牛首不仅是珍贵的文物,也是研究商代文化和艺术的重要资料。</speak>
INFO: connection closed
14:10:37.301 - INFO - 发送时检测到断开连接: 2cb47c8b-842c-47a8-b221-42caf74e089a,
14:10:37.301 - INFO - --- proxy AiChatTts audio_data_size=49671
14:10:38.255 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTM2NzkxMzB9.k-lALo9ulLGnu5O9qZALEp45F2loDnfdBZ09C9vglIw', 'balance': 0, 'status': 1, 'last_login_time': 1753074330, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1753074330, 'update_date': datetime.datetime(2025, 7, 21, 13, 5, 30)}
INFO: 43.144.107.210:0 - "GET /auth/verify HTTP/1.1" 200 OK
INFO: 43.144.107.28:0 - "POST /payment/get_user_museum_subscriptions HTTP/1.1" 200 OK
14:10:53.032 - INFO - 清理资源: 0会话
14:11:23.062 - INFO - 清理资源: 0会话
14:11:53.090 - INFO - 清理资源: 0会话
14:12:23.118 - INFO - 清理资源: 0会话
14:12:53.136 - INFO - 清理资源: 0会话
14:13:02.462 - INFO - verify_token user={'user_id': '9d0ba2ee-6821-4245-aadc-ea270313d92b', 'openid': 'obKSz7csdQWD7l4tqm7w_aoySrkM', 'phone': '18146525018', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5ZDBiYTJlZS02ODIxLTQyNDUtYWFkYy1lYTI3MDMxM2Q5MmIiLCJleHAiOjE3NTMwODcwMTd9.6z1_LMFK0vebxkel1H27Nx9OCyeHaOzASpNhL27Gjkk', 'balance': 0, 'status': 1, 'last_login_time': 1752482217, 'create_time': 1751012368, 'create_date': datetime.datetime(2025, 6, 27, 16, 19, 28), 'update_time': 1752482217, 'update_date': datetime.datetime(2025, 7, 14, 16, 36, 57)}
INFO: 43.140.60.33:0 - "GET /auth/verify HTTP/1.1" 200 OK
INFO: 43.144.107.28:0 - "POST /payment/get_user_museum_subscriptions HTTP/1.1" 200 OK
14:13:23.162 - INFO - 清理资源: 0会话
14:13:53.168 - INFO - 清理资源: 0会话
14:14:23.194 - INFO - 清理资源: 0会话
14:14:43.262 - INFO - wechat login data={'code': '0f1tbl1w35mEh530lf2w37qmFg4tbl1w', 'encryptedData': 'gBWrIB+qeddiOPRlaawf6ChAd2LqpA/4RxSwdeAr8JhDbHz2csnNl6QY0sWegHddLh4gUr5b3EZmWlTigEZIQa7PNqRVJviQczmGymKSU/X+iL7msmSbpPAcO7RZc6tzd8LdZYbYNcACW0qeCqmv7iyXx4FJzTFrKMF2L821N/F/xFe7yR2Sjf/w29/R9Rodqa4NnZNpUZ5QNRIOEwA8OQ==', 'iv': '5xb8I5Lx6PGh4zK2lwanpg=='}
14:14:43.896 - INFO - get_wx_session return {'session_key': 'Zx4n4H7AUgo18OKGcxTZ9w==', 'openid': 'obKSz7cpajH1Z6wECKSOLKXJ_XS8'}
14:14:43.900 - INFO - 解密数据: {'phoneNumber': '15901055018', 'purePhoneNumber': '15901055018', 'countryCode': '86', 'watermark': {'timestamp': 1753078481, 'appid': 'wx446813bfb3a6985a'}}
14:14:43.900 - INFO - decrypt_data return 15901055018
14:14:43.909 - INFO - login return {'user_id': '6dd06c74-902e-4f42-b226-d93b9ee5c1df', 'openid': 'obKSz7cpajH1Z6wECKSOLKXJ_XS8', 'phone': '15901055018', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2ZGQwNmM3NC05MDJlLTRmNDItYjIyNi1kOTNiOWVlNWMxZGYiLCJleHAiOjE3NTM0MzU4Mjh9.mZSLMkE5eDpJeIpurl3B2PFwxPPbwEkS-q3zPyhvqfo', 'balance': 0, 'status': 1, 'last_login_time': 1752831028, 'create_time': 1748941778, 'create_date': datetime.datetime(2025, 6, 3, 17, 9, 38), 'update_time': 1752831028, 'update_date': datetime.datetime(2025, 7, 18, 17, 30, 28)}
INFO: 43.144.107.210:0 - "POST /auth/login HTTP/1.1" 200 OK
14:14:44.535 - INFO - verify_token user={'user_id': '6dd06c74-902e-4f42-b226-d93b9ee5c1df', 'openid': 'obKSz7cpajH1Z6wECKSOLKXJ_XS8', 'phone': '15901055018', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2ZGQwNmM3NC05MDJlLTRmNDItYjIyNi1kOTNiOWVlNWMxZGYiLCJleHAiOjE3NTM2ODMyODN9.xBIu5A1efp5xcF10mH-GrJeSi_56BAMzfP3qVfugfhU', 'balance': 0, 'status': 1, 'last_login_time': 1753078483, 'create_time': 1748941778, 'create_date': datetime.datetime(2025, 6, 3, 17, 9, 38), 'update_time': 1753078483, 'update_date': datetime.datetime(2025, 7, 21, 14, 14, 43)}
INFO: 43.144.107.28:0 - "GET /auth/verify HTTP/1.1" 200 OK
INFO: 106.55.206.109:0 - "POST /payment/get_user_museum_subscriptions HTTP/1.1" 200 OK
14:14:53.223 - INFO - 清理资源: 0会话
14:14:58.786 - INFO - Creating TTS request: {'text': '提梁卣口径13.6厘米最大腹径22.2厘米通高26.8厘米2008年安阳刘家庄北地H326出土中国社会科学院考古研究所藏。器身扁圆形直口微敛长颈、鼓腹下垂矮圈足绹索状提梁两端饰小兽首。盖面饰两组独立兽面纹相背排列颈部饰八条勾喙夔纹腹部两组兽面纹以倒夔纹补空圈足饰八条夔纹。H326位于刘家庄北地两座商代夯土建筑间的通道中打破路土层推测为房主仓促撤离时埋藏。此卣填补了商末周初青铜器形制演变的空白。卣的器型特征为敛口颈部两侧有提梁鼓腹上有盖盖上有钮下有圈足。它的命名来自宋人器物上并不见自名。在不同时期的西周铭文涉及到有大量赏赐时多有“秬鬯一卣”的记录在这里“卣”是用作度量单位。鬯是酒的一种是黍与香草酿制用以降神。', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'model_name': 'sambert-zhichu-v1@Tongyi-Qianwen', 'sample_rate': 8000, 'stream_format': 'mp3'}
INFO: 43.144.107.210:0 - "POST /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts?device_id=17530784708251252320 HTTP/1.1" 200 OK
INFO: ('1.13.185.116', 37746) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/0f7bb773-8933-462a-805f-42f1adbc00fc" [accepted]
14:14:58.967 - INFO - 新连接建立: 1c2ac13f-9a2c-4bec-9241-13b5357c56f6
14:14:58.967 - INFO - 已经启动 start tts task {audio_stream_id}
14:14:58.967 - INFO - ---begin--init QwenTTS-- mp3 8000 sambert-zhichu-v1@Tongyi-Qianwen
INFO: connection open
14:14:58.967 - INFO - Qwen text_tts_call <speak>提梁卣口径13.6厘米最大腹径22.2厘米通高26.8厘米2008年安阳刘家庄北地H326出土中国社会科学院考古研究所藏。器身扁圆形直口微敛长颈、鼓腹下垂矮圈足绹索状提梁两端饰小兽首。盖面饰两组独立兽面纹相背排列颈部饰八条勾喙夔纹腹部两组兽面纹以倒夔纹补空圈足饰八条夔纹。H326位于刘家庄北地两座商代夯土建筑间的通道中打破路土层推测为房主仓促撤离时埋藏。此卣填补了商末周初青铜器形制演变的空白。卣的器型特征为敛口颈部两侧有提梁鼓腹上有盖盖上有钮下有圈足。它的命名来自宋人器物上并不见自名。在不同时期的西周铭文涉及到有大量赏赐时多有“秬鬯一卣”的记录在这里“卣”是用作度量单位。鬯是酒的一种是黍与香草酿制用以降神。</speak>
14:15:04.257 - INFO - --data_handler on_complete
14:15:04.257 - INFO - --tts task event set error = None
14:15:04.257 - INFO - UnifiedTTSEngine _run_tts_sync finally
INFO: connection closed
14:15:29.264 - INFO - Creating TTS request: {'text': '提梁卣口径13.6厘米最大腹径22.2厘米通高26.8厘米2008年安阳刘家庄北地H326出土中国社会科学院考古研究所藏。器身扁圆形直口微敛长颈、鼓腹下垂矮圈足绹索状提梁两端饰小兽首。盖面饰两组独立兽面纹相背排列颈部饰八条勾喙夔纹腹部两组兽面纹以倒夔纹补空圈足饰八条夔纹。H326位于刘家庄北地两座商代夯土建筑间的通道中打破路土层推测为房主仓促撤离时埋藏。此卣填补了商末周初青铜器形制演变的空白。卣的器型特征为敛口颈部两侧有提梁鼓腹上有盖盖上有钮下有圈足。它的命名来自宋人器物上并不见自名。在不同时期的西周铭文涉及到有大量赏赐时多有“秬鬯一卣”的记录在这里“卣”是用作度量单位。鬯是酒的一种是黍与香草酿制用以降神。', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'model_name': 'sambert-zhichu-v1@Tongyi-Qianwen', 'sample_rate': 8000, 'stream_format': 'mp3'}
INFO: 43.140.60.33:0 - "POST /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts?device_id=17510123186117505004 HTTP/1.1" 200 OK
INFO: ('1.13.185.116', 45602) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/1b664897-37ab-46c9-9140-70c44bd23d15" [accepted]
14:15:29.562 - INFO - 新连接建立: 344077b2-343f-4ac6-a37d-b83e81403078
14:15:29.562 - INFO - 已经启动 start tts task {audio_stream_id}
14:15:29.562 - INFO - ---begin--init QwenTTS-- mp3 8000 sambert-zhichu-v1@Tongyi-Qianwen
14:15:29.562 - INFO - Qwen text_tts_call <speak>提梁卣口径13.6厘米最大腹径22.2厘米通高26.8厘米2008年安阳刘家庄北地H326出土中国社会科学院考古研究所藏。器身扁圆形直口微敛长颈、鼓腹下垂矮圈足绹索状提梁两端饰小兽首。盖面饰两组独立兽面纹相背排列颈部饰八条勾喙夔纹腹部两组兽面纹以倒夔纹补空圈足饰八条夔纹。H326位于刘家庄北地两座商代夯土建筑间的通道中打破路土层推测为房主仓促撤离时埋藏。此卣填补了商末周初青铜器形制演变的空白。卣的器型特征为敛口颈部两侧有提梁鼓腹上有盖盖上有钮下有圈足。它的命名来自宋人器物上并不见自名。在不同时期的西周铭文涉及到有大量赏赐时多有“秬鬯一卣”的记录在这里“卣”是用作度量单位。鬯是酒的一种是黍与香草酿制用以降神。</speak>
INFO: connection open
14:15:34.797 - INFO - --data_handler on_complete
14:15:34.797 - INFO - --tts task event set error = None
14:15:34.797 - INFO - UnifiedTTSEngine _run_tts_sync finally
INFO: connection closed
14:15:34.848 - INFO - 发送时检测到断开连接: 344077b2-343f-4ac6-a37d-b83e81403078,
INFO: ('1.13.185.116', 48856) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/54697bbc-a6ca-49c3-97a5-b73ac4e30bc9" [accepted]
14:16:25.962 - INFO - 新连接建立: e030143e-537e-4b14-a3ee-6594e50a1711
INFO: connection open
14:16:25.995 - INFO - 代理文本流: completions_url=http://127.0.0.1:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions {'question': '请简单介绍兽面纹铜觚,字符不超过150字', 'stream': True, 'tts_model': 'sambert-zhichu-v1@Tongyi-Qianwen', 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'tts_disable': True}
14:16:28.918 - INFO - HTTP Request: POST http://127.0.0.1:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions "HTTP/1.1 200 OK"
14:16:28.918 - INFO - 响应状态: HTTP 200
14:16:28.918 - INFO - ---begin--init QwenTTS-- mp3 8000 sambert-zhichu-v1@Tongyi-Qianwen
14:16:31.918 - ERROR - create_session Timeout acquiring lock for session creation
14:16:31.919 - INFO - 开始处理SSE流
14:16:31.919 - INFO - --proxy_aichat_text_stream 发送audio_stream_url

View File

@@ -1,8 +1,8 @@
from pymysql.cursors import DictCursor from pymysql.cursors import DictCursor
DATABASE_CONFIG = { DATABASE_CONFIG = {
"host": "localhost", "host": "localhost",#"ragflow-mysql",#"localhost",
"port": 5455, "port": 5455,#3306, #5455,
"user": "root", "user": "root",
"password": "infini_rag_flow", "password": "infini_rag_flow",
"database": "rag_flow", "database": "rag_flow",

View File

@@ -2,7 +2,7 @@ import pymysql
from pymysql import Connection from pymysql import Connection
from pymysql.err import OperationalError, InterfaceError from pymysql.err import OperationalError, InterfaceError
from contextlib import contextmanager from contextlib import contextmanager
from config import DATABASE_CONFIG from app.config import DATABASE_CONFIG
from datetime import datetime,timedelta from datetime import datetime,timedelta
import logging import logging
from zoneinfo import ZoneInfo # Python 3.9+ 内置 from zoneinfo import ZoneInfo # Python 3.9+ 内置

View File

@@ -9,7 +9,7 @@ from Crypto.Cipher import AES
import base64,uuid,asyncio import base64,uuid,asyncio
import requests import requests
from datetime import datetime,timedelta from datetime import datetime,timedelta
from database import * from app.database import *
login_router = APIRouter() login_router = APIRouter()
logger = logging.getLogger("login") logger = logging.getLogger("login")

View File

@@ -9,10 +9,18 @@ import json
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from dotenv import load_dotenv from dotenv import load_dotenv
import uvicorn import uvicorn
# 加载 .env 文件中的环境变量
load_dotenv() # 默认加载项目根目录的 .env 文件
from app.asr_service import asr_router
from app.monitor_service import monitor_router
from app.tts_service import tts_router,tts_lifespan
from app.login_service import login_router
from app.chat_service import chat_router
from app.payment_service import payment_router
@asynccontextmanager @asynccontextmanager
async def lifespan(app: FastAPI): async def lifespan(app: FastAPI):
"""生命周期管理""" """生命周期管理"""
@@ -20,21 +28,17 @@ async def lifespan(app: FastAPI):
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
print(" ASR & Monitor Service Start") print(" ASR & Monitor Service Start")
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
# 启动TTS路由器的生命周期
tts_lifespan_ctx = tts_lifespan(app)
await tts_lifespan_ctx.__aenter__()
yield yield
# 关闭TTS路由器的生命周期
await tts_lifespan_ctx.__aexit__(None, None, None)
# 服务停止清理 # 服务停止清理
print("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") print("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
print(" Service Stopped Cleanly") print(" Service Stopped Cleanly")
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━") print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
# 加载 .env 文件中的环境变量
load_dotenv() # 默认加载项目根目录的 .env 文件
from app.asr_service import asr_router
from app.monitor_service import monitor_router
from app.tts_service import tts_router
from app.login_service import login_router
from app.chat_service import chat_router
from app.payment_service import payment_router
# 创建应用实例 # 创建应用实例
app = FastAPI(lifespan=lifespan) app = FastAPI(lifespan=lifespan)

View File

@@ -12,9 +12,8 @@ from decimal import Decimal
from uuid import UUID from uuid import UUID
import json import json
import logging import logging
from database import * from app.database import *
from jose import JWTError, jwt from jose import JWTError, jwt
from database import *
import base64 import base64
from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.asymmetric import padding

View File

@@ -1,3 +0,0 @@
#!/bin/bash
export PYTHONPATH=.
python3 -m main.py

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,8 @@
# 需要准备 docker compose .yml 和 Dockerfile 文件 # 需要准备 docker compose .yml 和 Dockerfile 文件
networks: networks:
docker_ragflow: docker_ragflow:
external: true # 声明使用外部网络(需提前创建) external: true # 声明使用外部网络(需提前创建)
services: services:
asr-monitor-test: asr-monitor-test:
build: build:

View File

@@ -3,6 +3,7 @@ uvicorn>=0.15.0
websockets==12.0 websockets==12.0
python-multipart==0.0.20 python-multipart==0.0.20
dashscope>=1.23.8
# JWT 相关 # JWT 相关
python-jose[cryptography]==3.3.0 # 兼容 Python3 的 JOSE 实现 python-jose[cryptography]==3.3.0 # 兼容 Python3 的 JOSE 实现
@@ -15,6 +16,7 @@ httpx
# MySQL 驱动 # MySQL 驱动
pymysql==1.1.0 pymysql==1.1.0
tzdata==2025.2
# 连接池管理 # 连接池管理
dbutils==3.1.1 dbutils==3.1.1

View File

@@ -20,8 +20,10 @@ export PYTHONPATH=.:$PYTHONPATH
# 3. 使用nohup运行并防止终端退出影响 # 3. 使用nohup运行并防止终端退出影响
echo "➜ 启动应用进程..." echo "➜ 启动应用进程..."
nohup python app/main.py > app.log 2>&1 & #nohup python app/main.py > app.log 2>&1 &
#只能使用1个worker共享全局变量使用会有问题
nohup uvicorn app.main:app --host 0.0.0.0 --port 9580 --workers 4 > app.log 2>&1 &
# 4. 验证新进程 # 4. 验证新进程
sleep 3 # 等待进程启动 sleep 3 # 等待进程启动
NEW_PID=$(lsof -ti :${PORT}) NEW_PID=$(lsof -ti :${PORT})

View File

@@ -13,4 +13,13 @@ else
fi fi
source venv/bin/activate source venv/bin/activate
export PYTHONPATH=.:$PYTHONPATH && python app/main.py export PYTHONPATH=.:$PYTHONPATH
#python app/main.py
# 高性能启动 FastAPI
uvicorn app.main:app \
--host 0.0.0.0 \
--port $PORT \
--workers 4 \
--timeout-keep-alive 65 \
--no-access-log