|
@@ -0,0 +1,341 @@
|
|
|
+
|
|
|
+
|
|
|
+"""
|
|
|
+-----------------File Info-----------------------
|
|
|
+Name: web.py
|
|
|
+Description: web api support
|
|
|
+Author: GentleCP
|
|
|
+Email: me@gentlecp.com
|
|
|
+Create Date: 2021/6/19
|
|
|
+-----------------End-----------------------------
|
|
|
+"""
|
|
|
+import json
|
|
|
+import re
|
|
|
+import sys
|
|
|
+import threading
|
|
|
+import time
|
|
|
+import uuid
|
|
|
+
|
|
|
+from xml.etree.ElementTree import fromstring
|
|
|
+
|
|
|
+import requests
|
|
|
+import uvicorn
|
|
|
+from fastapi import FastAPI, Response, Request, BackgroundTasks, Body
|
|
|
+
|
|
|
+from WXBizMsgCrypt3 import WXBizMsgCrypt
|
|
|
+from commom import get_logger, request_id_context
|
|
|
+
|
|
|
+logger = get_logger()
|
|
|
+
|
|
|
+
|
|
|
+with open('znjd_config_test.json', 'r') as f:
|
|
|
+ config = json.load(f)
|
|
|
+
|
|
|
+
|
|
|
+token = config['token']
|
|
|
+aeskey = config['aeskey']
|
|
|
+corpid = config['corpid']
|
|
|
+corpsecret = config['corpsecret']
|
|
|
+coze_access_token = config['coze_access_token']
|
|
|
+bot_id = config['bot_id']
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+wxcpt = WXBizMsgCrypt(token, aeskey, corpid)
|
|
|
+
|
|
|
+
|
|
|
+app = FastAPI()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def call_llm(user_query: str, bot_id: str,coze_access_token:str,company_name:str):
|
|
|
+ req_head = {
|
|
|
+ "Authorization":f"Bearer {coze_access_token}",
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ }
|
|
|
+ req_data ={
|
|
|
+ "bot_id": bot_id,
|
|
|
+ "user_id": "123456789",
|
|
|
+ "stream": False,
|
|
|
+ "auto_save_history": True,
|
|
|
+
|
|
|
+ "additional_messages": [
|
|
|
+ {
|
|
|
+ "role": "user",
|
|
|
+ "content": user_query,
|
|
|
+ "content_type": "text"
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+ res_create = requests.post(" https://api.coze.cn/v1/conversation/create", headers=req_head)
|
|
|
+ conversation_id = res_create.json()["data"]["id"]
|
|
|
+ res_chat = requests.post(f" https://api.coze.cn/v3/chat?conversation_id={conversation_id}", headers=req_head,json=req_data)
|
|
|
+
|
|
|
+ chat_id = res_chat.json()["data"]["id"]
|
|
|
+ while True:
|
|
|
+ res_retrieve = requests.get(f" https://api.coze.cn/v3/chat/retrieve?chat_id={chat_id}&conversation_id={conversation_id}", headers=req_head)
|
|
|
+ res_json = res_retrieve.json()
|
|
|
+
|
|
|
+ if res_retrieve.status_code != 200:
|
|
|
+ logger.error(f"网络状态码失败,错误码:{res_retrieve.status_code }")
|
|
|
+ coze_response = f"网络状态码失败,错误码:{res_retrieve.status_code }"
|
|
|
+ url = ""
|
|
|
+ return coze_response,company_name,url
|
|
|
+
|
|
|
+ if res_json["code"] != 0 :
|
|
|
+ logger.error(f"API调用失败,错误码:{res_json['code']}")
|
|
|
+ coze_response = f"API调用失败,错误码:{res_json['code']}"
|
|
|
+ url = ""
|
|
|
+ return coze_response,company_name,url
|
|
|
+
|
|
|
+ logger.info(res_json["data"]["status"])
|
|
|
+ status = res_json["data"]["status"]
|
|
|
+
|
|
|
+ error_statuses = {"failed", "requires_action", "canceled"}
|
|
|
+ if status in error_statuses:
|
|
|
+ error_message = res_json["data"]["last_error"]
|
|
|
+ logger.error(f"对话错误,状态:{status},错误信息:{error_message}")
|
|
|
+ coze_response = f"对话错误,状态:{status},错误信息:{error_message}"
|
|
|
+ url = ""
|
|
|
+ return coze_response,company_name,url
|
|
|
+
|
|
|
+ if status == "completed":
|
|
|
+ res_message = requests.get(f"https://api.coze.cn/v3/chat/message/list?chat_id={chat_id}&conversation_id={conversation_id}", headers=req_head)
|
|
|
+ aa = res_message.json()
|
|
|
+
|
|
|
+
|
|
|
+ data = res_message.json()['data']
|
|
|
+
|
|
|
+
|
|
|
+ last_answer_record = next((record for record in reversed(data) if record['type'] == 'answer'), None)
|
|
|
+
|
|
|
+
|
|
|
+ if last_answer_record:
|
|
|
+ report_link = last_answer_record['content'].replace(" ", "")
|
|
|
+ url_start_index = report_link.find('http')
|
|
|
+ url = report_link[url_start_index:]
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ coze_response = f'[{company_name}报告下载链接]({url}) - 原始链接:[{url}]({url})'
|
|
|
+
|
|
|
+
|
|
|
+ else:
|
|
|
+
|
|
|
+ coze_response = f"{company_name}报告未生成"
|
|
|
+ url = ""
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return coze_response,company_name,url
|
|
|
+ time.sleep(1)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def qiwei_get():
|
|
|
+ res = requests.get(f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={corpsecret}")
|
|
|
+ qw_access_token = res.json()["access_token"]
|
|
|
+ return qw_access_token
|
|
|
+
|
|
|
+def qiwei_post_text(username: str, answer: str,agentid:str):
|
|
|
+ req_data = {
|
|
|
+ "touser": username,
|
|
|
+ "toparty": "",
|
|
|
+ "totag": "",
|
|
|
+ "msgtype": "text",
|
|
|
+ "agentid": agentid,
|
|
|
+ "text": {"content": answer},
|
|
|
+ "image": {
|
|
|
+ "media_id": "MEDIA_ID"
|
|
|
+ },
|
|
|
+ "safe": 0,
|
|
|
+ "enable_id_trans": 0,
|
|
|
+ "enable_duplicate_check": 0,
|
|
|
+ "duplicate_check_interval": 1800
|
|
|
+ }
|
|
|
+
|
|
|
+ res = requests.post(f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={qiwei_get()}", json=req_data)
|
|
|
+
|
|
|
+ logger.info(res.json())
|
|
|
+
|
|
|
+
|
|
|
+def qiwei_post_card(username: str, answer: str,agentid:str,company_name:str,url:str):
|
|
|
+ req_data ={
|
|
|
+ "touser": username,
|
|
|
+ "toparty": "",
|
|
|
+ "totag": "",
|
|
|
+ "msgtype": "textcard",
|
|
|
+ "agentid": agentid,
|
|
|
+ "textcard": {
|
|
|
+ "title": f"报告已生成(请在十分钟内点击下载)",
|
|
|
+ "description": f"<div class=\"gray\">{company_name}报告下载链接</div> ",
|
|
|
+ "url": url,
|
|
|
+ "btntxt": ""
|
|
|
+ },
|
|
|
+ "enable_id_trans": 0,
|
|
|
+ "enable_duplicate_check": 0,
|
|
|
+ "duplicate_check_interval": 1800
|
|
|
+ }
|
|
|
+
|
|
|
+ res = requests.post(f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={qiwei_get()}", json=req_data)
|
|
|
+
|
|
|
+ logger.info(res.json())
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def post_consumer_api(user_query, decrypt_data, request_id,company_name):
|
|
|
+ data = {
|
|
|
+ "user_query": user_query,
|
|
|
+ "decrypt_data": decrypt_data,
|
|
|
+ "request_id": request_id,
|
|
|
+ "company_name":company_name,
|
|
|
+ }
|
|
|
+ request_id_context.set(request_id)
|
|
|
+ url = "https://101.126.81.2:18092/consumer"
|
|
|
+ try:
|
|
|
+ logger.info(f"post_consumer_api 被执行{user_query}")
|
|
|
+ t1 = threading.Thread(target=requests.post, kwargs={"url": url, "json": data, "verify": False})
|
|
|
+ t1.start()
|
|
|
+ logger.info(f"post_consumer_api 请求成功: {t1}")
|
|
|
+ except requests.exceptions.RequestException as e:
|
|
|
+ logger.error(f"post_consumer_api 请求失败: {e}")
|
|
|
+
|
|
|
+@app.post("/consumer")
|
|
|
+def consumer(
|
|
|
+ request_id: str = Body(...),
|
|
|
+ user_query: str = Body(...),
|
|
|
+ decrypt_data: dict = Body(...),
|
|
|
+ company_name: str = Body(...),
|
|
|
+):
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ request_id_context.set(request_id)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ username = decrypt_data.get('FromUserName', '')
|
|
|
+ agentid = decrypt_data.get('AgentID', '')
|
|
|
+ qiwei_post_text(username, "正在加载,请稍后,预计2分钟...", agentid)
|
|
|
+ logger.info("正在加载,请稍后,预计2分钟...")
|
|
|
+ logger.info(f"consumer 请求:{user_query}")
|
|
|
+
|
|
|
+
|
|
|
+ coze_response,company_name,url = call_llm(user_query=user_query,bot_id=bot_id,coze_access_token = coze_access_token,company_name= company_name)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ answer = coze_response
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ logger.info(f"结果:{answer}")
|
|
|
+
|
|
|
+ qiwei_post_card(username, answer, agentid,company_name,url)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+@app.get("/ok")
|
|
|
+async def ok():
|
|
|
+ return "ok"
|
|
|
+
|
|
|
+
|
|
|
+@app.get("/bot")
|
|
|
+async def verify(msg_signature: str, timestamp: str, nonce: str, echostr: str):
|
|
|
+ ret, sEchoStr = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr)
|
|
|
+ if ret == 0:
|
|
|
+ return Response(content=sEchoStr.decode('utf-8'))
|
|
|
+ else:
|
|
|
+
|
|
|
+ logger.info(sEchoStr)
|
|
|
+
|
|
|
+
|
|
|
+user_bot_id_mapping = {}
|
|
|
+
|
|
|
+@app.post("/bot")
|
|
|
+async def recv(msg_signature: str, timestamp: str, nonce: str, request: Request, background_tasks: BackgroundTasks):
|
|
|
+
|
|
|
+ body = await request.body()
|
|
|
+ request_id = str(uuid.uuid4())
|
|
|
+ request_id_context.set(request_id)
|
|
|
+ ret, sMsg = wxcpt.DecryptMsg(body.decode('utf-8'), msg_signature, timestamp, nonce)
|
|
|
+ decrypt_data = {}
|
|
|
+ for node in list(fromstring(sMsg.decode('utf-8'))):
|
|
|
+ decrypt_data[node.tag] = node.text
|
|
|
+
|
|
|
+
|
|
|
+ company_name = decrypt_data.get('Content', '')
|
|
|
+
|
|
|
+ logger.info(f"start user_query: {company_name}")
|
|
|
+ logger.info(f"start request_id: {request_id}")
|
|
|
+ user_query = f"""query:{company_name}
|
|
|
+ request_id: {request_id}"""
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ logger.info(f"start prompt: {user_query}")
|
|
|
+
|
|
|
+ post_consumer_api(user_query, decrypt_data, request_id, company_name)
|
|
|
+ return Response(content="")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+
|
|
|
+
|
|
|
+ try:
|
|
|
+ port = sys.argv[1]
|
|
|
+ int(port)
|
|
|
+ except:
|
|
|
+ port = 18091
|
|
|
+ request_id_context.set("app start")
|
|
|
+ logger.info(f'{port=}')
|
|
|
+ print(f'{port=}')
|
|
|
+ uvicorn.run("coze_znjd_api_test:app", port=int(port), host='0.0.0.0', reload=False,ssl_keyfile="./key.pem", ssl_certfile="./cert.pem")
|