From b9addbf3f159c8e7673f2e9ecc3fa78e73283182 Mon Sep 17 00:00:00 2001
From: xqz <837938965@qq.com>
Date: 星期四, 03 七月 2025 10:35:06 +0800
Subject: [PATCH] 7.3 qwen
---
smart_detecttest1111.py | 261 +++++
qwen_ollama_detect.py | 219 ++++
qwen_vllm_detect.py | 256 +++++
qwen_ollama.py | 332 ++++++
qwen_vllm.py | 246 ++++
qwen_task.py | 150 ++
qwen_vllm_thread.py | 91 +
get_mem.py | 318 ++++++
int.txt | 33
vllm.py | 62 +
/dev/null | 1
qwen_detect.py | 234 ++++
detect_task1111.py | 209 ++++
qwen_test.py | 36
conf.txt | 14
b.py | 357 +++++++
temp.jpg | 0
a.py | 232 ++++
SimSun.ttf | 0
19 files changed, 3,050 insertions(+), 1 deletions(-)
diff --git a/22.txt b/22.txt
deleted file mode 100644
index 9f54fe3..0000000
--- a/22.txt
+++ /dev/null
@@ -1 +0,0 @@
-122
diff --git a/SimSun.ttf b/SimSun.ttf
new file mode 100644
index 0000000..e0115ab
--- /dev/null
+++ b/SimSun.ttf
Binary files differ
diff --git a/a.py b/a.py
new file mode 100644
index 0000000..2a88611
--- /dev/null
+++ b/a.py
@@ -0,0 +1,232 @@
+
+import threading
+import time as time_sel
+from typing import Dict
+import qwen_task
+import requests
+import os
+import torch
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+ def __init__(self):
+ #璇诲彇閰嶇疆鏂囦欢
+ self.config = {}
+ with open('./conf.txt', 'r', encoding='utf-8') as file:
+ for line in file:
+ # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+ line = line.strip()
+ # 璺宠繃绌鸿
+ if not line:
+ continue
+ # 鍒嗗壊閿拰鍊�
+ if '=' in line:
+ key, value = line.split('=', 1)
+ # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+ key = key.strip()
+ value = value.strip()
+ # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+ self.config[key] = value
+ # 閰嶇疆鏃ュ織
+ # 纭繚鏃ュ織鐩綍瀛樺湪
+ log_dir = "logs"
+ os.makedirs(log_dir, exist_ok=True)
+ self.threads: Dict[str, threading.Thread] = {}
+ self.lock = threading.Lock()
+
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
+ # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+ # 鎸囧畾鏈湴璺緞
+ model_path = "./Qwen2.5-VL-3B-Instruct-AWQ"
+ # 鍔犺浇妯″瀷
+ self.qwen_model = AutoModelForVision2Seq.from_pretrained(
+ model_path,
+ device_map="auto"
+ ).eval()
+ # 鍔犺浇澶勭悊鍣�
+ self.qwen_tokenizer = AutoProcessor.from_pretrained(model_path,use_fast=True)
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+ # 鍔犺浇闆嗗悎
+ self.collection = Collection(name="smartobject")
+ self.collection.load()
+
+ #鏄惁鏇存柊
+ self._isupdate = False
+
+ # 鍒濆鍖栧叡浜唴瀛�
+ get_mem.smem_init()
+
+ # 閰嶇疆鏃ュ織
+ logging.basicConfig(
+ level=logging.INFO,
+ format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S',
+ handlers=[
+ # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+ RotatingFileHandler(
+ filename=os.path.join(log_dir, 'start_log.log'),
+ maxBytes=10 * 1024 * 1024, # 10MB
+ backupCount=3,
+ encoding='utf-8'
+ ),
+ # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+ logging.StreamHandler()
+ ]
+ )
+
+ #鍚姩绾跨▼
+ def safe_start(self, target_func, camera_id):
+ """绾跨▼瀹夊叏鍚姩鏂规硶"""
+ def wrapped():
+ thread_name = threading.current_thread().name
+ try:
+ target_func(camera_id)
+ except Exception as e:
+ logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+ with self.lock: # 纭繚绾跨▼瀹夊叏鍒涘缓
+ t = threading.Thread(
+ target=wrapped,
+ daemon=True # 璁剧疆涓哄畧鎶ょ嚎绋�
+ )
+ t.start()
+ self.threads[camera_id] = t
+ return t
+
+ # 鍚姩绾跨▼浠诲姟
+ def worker(self, camera_id):
+ # 鍒濆鍖�
+ detect = qwen_task.detect_tasks()
+ detect._thread_name = f"{camera_id}" # 璁剧疆鍚嶇О
+ detect.init_logging(f"{camera_id}")
+ # 鍒濆鍖栨娴嬫ā鍨�
+ detect.device = self.device
+ # 鍒濆鍖杚wen妯″瀷
+ detect.qwen_tokenizer = self.qwen_tokenizer
+ detect.qwen_model = self.qwen_model
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ detect.collection = self.collection
+
+ # 璁剧疆绾跨▼鍚姩鐘舵��
+ detect._running = True
+ try:
+ # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+ image_id_list = [458671636370971032]
+ for image_id in image_id_list:
+ logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+ image_id = detect.tark_do(image_id,self.config.get("filesavepath"),self.config.get("ragurl"),self.config.get("max_tokens"))
+ logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+ except Exception as e:
+ logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+ #璋冪敤鏄惁闇�瑕佹洿鏂�
+ def isUpdate(self):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("isupdateurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json().get("data")
+ if data.get("isChange") == 1:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+ return False
+
+ #淇敼鏄惁鏇存柊鐘舵��
+ def update_status(self):
+ try:
+ # 鏇存柊鐘舵��
+ url = self.config.get("updatestatusurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.post(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+ return False
+
+ def shutdown_all(self) -> None:
+ """娓呯悊鎵�鏈夌嚎绋�"""
+ with self.lock:
+ for camera_id, thread in list(self.threads.items()):
+ if thread.is_alive():
+ thread.join(timeout=1)
+ del self.threads[camera_id]
+
+ #鑾峰彇浠诲姟
+ def getTaskconf(self,isupdate):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("gettaskconfurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json()
+ if isupdate:
+ # 鏇存柊鐘舵��
+ self.update_status()
+ return data.get("data")
+ else:
+ return []
+ except Exception as e:
+ logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+ return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+ pool = ThreadPool()
+ is_init = True
+ camera_data = pool.getTaskconf(False)
+ while True:
+ try:
+ pool._isupdate = False # 鏄惁鏇存柊鏁版嵁
+ # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+ if pool.isUpdate():
+ # 鑾峰彇鎽勫儚鏈轰换鍔�
+ camera_data = pool.getTaskconf(True)
+ pool._isupdate = True # 鏇存柊鏁版嵁
+
+ if is_init:
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ if pool._isupdate:
+ logging.info(f"鏇存柊绾跨▼寮�濮�")
+ pool.shutdown_all()
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+ is_init = False
+ time_sel.sleep(1)
+ except Exception as e:
+ logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/b.py b/b.py
new file mode 100644
index 0000000..8e33ca6
--- /dev/null
+++ b/b.py
@@ -0,0 +1,357 @@
+
+import threading
+import time as time_sel
+from typing import Dict
+import qwen_task
+import requests
+import os
+import torch
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+ def __init__(self):
+ #璇诲彇閰嶇疆鏂囦欢
+ self.config = {}
+ with open('./conf.txt', 'r', encoding='utf-8') as file:
+ for line in file:
+ # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+ line = line.strip()
+ # 璺宠繃绌鸿
+ if not line:
+ continue
+ # 鍒嗗壊閿拰鍊�
+ if '=' in line:
+ key, value = line.split('=', 1)
+ # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+ key = key.strip()
+ value = value.strip()
+ # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+ self.config[key] = value
+ # 閰嶇疆鏃ュ織
+ # 纭繚鏃ュ織鐩綍瀛樺湪
+ log_dir = "logs"
+ os.makedirs(log_dir, exist_ok=True)
+ self.threads: Dict[str, threading.Thread] = {}
+ self.lock = threading.Lock()
+
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
+ # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+ # 鎸囧畾鏈湴璺緞
+ model_path = "./Qwen2-VL-2B-Instruct"
+ # 鍔犺浇妯″瀷
+ self.qwen_model = AutoModelForVision2Seq.from_pretrained(
+ model_path,
+ device_map="auto", # 鑷姩鍒嗛厤GPU
+ torch_dtype=torch.float16, # 鍗婄簿搴﹁妭鐪佹樉瀛�
+ trust_remote_code=True # 鍏佽鎵ц鑷畾涔変唬鐮�
+ ).eval()
+ # 鍔犺浇澶勭悊鍣�
+ self.qwen_tokenizer = AutoProcessor.from_pretrained(model_path)
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+ # 鍔犺浇闆嗗悎
+ self.collection = Collection(name="smartobject")
+ self.collection.load()
+
+ #鏄惁鏇存柊
+ self._isupdate = False
+
+ # 鍒濆鍖栧叡浜唴瀛�
+ get_mem.smem_init()
+
+ # 閰嶇疆鏃ュ織
+ logging.basicConfig(
+ level=logging.INFO,
+ format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S',
+ handlers=[
+ # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+ RotatingFileHandler(
+ filename=os.path.join(log_dir, 'start_log.log'),
+ maxBytes=10 * 1024 * 1024, # 10MB
+ backupCount=3,
+ encoding='utf-8'
+ ),
+ # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+ logging.StreamHandler()
+ ]
+ )
+
+ #鍚姩绾跨▼
+ def safe_start(self, target_func, camera_id):
+ """绾跨▼瀹夊叏鍚姩鏂规硶"""
+ def wrapped():
+ thread_name = threading.current_thread().name
+ try:
+ target_func(camera_id)
+ except Exception as e:
+ logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+ with self.lock: # 纭繚绾跨▼瀹夊叏鍒涘缓
+ t = threading.Thread(
+ target=wrapped,
+ daemon=True # 璁剧疆涓哄畧鎶ょ嚎绋�
+ )
+ t.start()
+ self.threads[camera_id] = t
+ return t
+
+ # 鍚姩绾跨▼浠诲姟
+ def worker(self, camera_id):
+ # 鍒濆鍖�
+ detect = qwen_task.detect_tasks()
+ detect._thread_name = f"{camera_id}" # 璁剧疆鍚嶇О
+ detect.init_logging(f"{camera_id}")
+ # 鍒濆鍖栨娴嬫ā鍨�
+ detect.device = self.device
+ # 鍒濆鍖杚wen妯″瀷
+ detect.qwen_tokenizer = self.qwen_tokenizer
+ detect.qwen_model = self.qwen_model
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ detect.collection = self.collection
+
+ # 璁剧疆绾跨▼鍚姩鐘舵��
+ detect._running = True
+ try:
+ # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+ image_id_list = [458450378519380938,
+458450378519380940,
+458450378519380942,
+458450378519380944,
+458450378519380946,
+458450378519380948,
+458450378519380950,
+458450378519380952,
+458450378519380954,
+458450378519380956,
+458450378519380958,
+458450378519380960,
+458450378519380962,
+458450378519380964,
+0,
+458450378519380966,
+458450378519380968,
+0,
+458450378519380970,
+458450378519380972,
+458450378519380974,
+458450378519380976,
+458450378519380978,
+458450378519380980,
+458450378519380982,
+458450378519380984,
+458450378519380986,
+458450378519380988,
+458450378519380990,
+458450378519380992,
+0,
+458450378519380994,
+458450378519380996,
+0,
+458450378519380998,
+458450378519381000,
+0,
+458450378519381002,
+458450378519381004,
+458450378519381006,
+0,
+458450378519381008,
+458450378519381010,
+458450378519381012,
+458450378519381014,
+458450378519381016,
+458450378519381018,
+458450378519381020,
+458450378519381022,
+458450378519381024,
+458450378519381026,
+458450378519381028,
+458450378519381030,
+458450378519381032,
+458450378519381034,
+458450378519381036,
+458450378519381038,
+458450378519381040,
+458450378519381042,
+458450378519381044,
+458450378519381046,
+0,
+458450378519381048,
+458450378519381050,
+458450378519381052,
+458450378519381054,
+458450378519381056,
+458450378519381058,
+458450378519381060,
+458450378519381062,
+458450378519381064,
+458450378519381066,
+458450378519381068,
+458450378519381070,
+458450378519381072,
+458450378519381074,
+458450378519381076,
+458450378519381078,
+458450378519381080,
+458450378519381082,
+458450378519381084,
+0,
+458450378519381086,
+458450378519381088,
+458450378519381090,
+458450378519381092,
+458450378519381094,
+458450378519381096,
+458450378519381098,
+458450378519381100,
+458450378519381102,
+458450378519381104,
+458450378519381106,
+458450378519381108,
+458450378519381110,
+458450378519381112,
+458450378519381114,
+458450378519381116,
+458450378519381118,
+458450378519381120,
+458450378519381122,
+458450378519381124,
+458450378519381126,
+0,
+458450378519381128,
+458450378519381130,
+458450378519381132,
+458450378519381134,
+458450378519381136,
+458450378519381138,
+458450378519381140,
+458450378519381142,
+458450378519381144,
+458450378519381146,
+458450378519381148,
+458450378519381150,
+458450378519381152,
+458450378519381154,
+458450378519381156,
+458450378519381158
+]
+
+
+
+ for image_id in image_id_list:
+ logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+ image_id = detect.tark_do(image_id,self.config.get("filesavepath"),self.config.get("ragurl"),self.config.get("max_tokens"))
+ logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+ except Exception as e:
+ logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+ #璋冪敤鏄惁闇�瑕佹洿鏂�
+ def isUpdate(self):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("isupdateurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json().get("data")
+ if data.get("isChange") == 1:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+ return False
+
+ #淇敼鏄惁鏇存柊鐘舵��
+ def update_status(self):
+ try:
+ # 鏇存柊鐘舵��
+ url = self.config.get("updatestatusurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.post(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+ return False
+
+ def shutdown_all(self) -> None:
+ """娓呯悊鎵�鏈夌嚎绋�"""
+ with self.lock:
+ for camera_id, thread in list(self.threads.items()):
+ if thread.is_alive():
+ thread.join(timeout=1)
+ del self.threads[camera_id]
+
+ #鑾峰彇浠诲姟
+ def getTaskconf(self,isupdate):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("gettaskconfurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json()
+ if isupdate:
+ # 鏇存柊鐘舵��
+ self.update_status()
+ return data.get("data")
+ else:
+ return []
+ except Exception as e:
+ logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+ return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+ pool = ThreadPool()
+ is_init = True
+ camera_data = pool.getTaskconf(False)
+ while True:
+ try:
+ pool._isupdate = False # 鏄惁鏇存柊鏁版嵁
+ # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+ if pool.isUpdate():
+ # 鑾峰彇鎽勫儚鏈轰换鍔�
+ camera_data = pool.getTaskconf(True)
+ pool._isupdate = True # 鏇存柊鏁版嵁
+
+ if is_init:
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ if pool._isupdate:
+ logging.info(f"鏇存柊绾跨▼寮�濮�")
+ pool.shutdown_all()
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+ is_init = False
+ time_sel.sleep(1)
+ except Exception as e:
+ logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/conf.txt b/conf.txt
new file mode 100644
index 0000000..4d67331
--- /dev/null
+++ b/conf.txt
@@ -0,0 +1,14 @@
+milvusurl = 192.168.1.232
+milvusport = 19530
+isupdateurl = http://192.168.1.232:8088/v1/task/isChange?stateType=2
+gettaskconfurl = http://192.168.1.232:8088/v1/task/getTaskConf
+updatestatusurl = http://192.168.1.232:8088/v1/task/updateChangeStatus?stateType=2
+videotaskurl = http://192.168.1.232:8089/api/v1/camera/record/task
+ragurl=http://192.168.1.232:8870
+ragmode=qwen2.5vl
+ollamaurl=http://192.168.1.232:11434
+ollamamode=qwen2.5vl
+filesavepath = /opt/smart
+max_tokens = 2000
+threadnum = 10
+
diff --git a/detect_task1111.py b/detect_task1111.py
new file mode 100644
index 0000000..b5462f8
--- /dev/null
+++ b/detect_task1111.py
@@ -0,0 +1,209 @@
+import os
+import logging
+from logging.handlers import RotatingFileHandler
+
+import cv2
+import torch
+from PIL import Image
+from pymilvus import connections, Collection
+from transformers import AutoTokenizer, AutoModelForVision2Seq, AutoProcessor, BitsAndBytesConfig
+from flask import Flask, request, jsonify
+
+app = Flask(__name__)
+#瑙勫垯姣斿
+def cross_collection_vector_compare(self,image_id,video_point_id,rule_id,video_image_time,frame_id,task_id,video_path,videotaskurl):
+ try:
+ # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ res_a = self.collection.query(
+ expr=f"id in {image_id}",
+ output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+ "video_point_id", "detect_num", "detect_id", "detect_time", "image_path", "video_path"],
+ consistency_level="Strong"
+ )
+
+ # 2. 浠庨泦鍚圔鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ res_b = self.collection_rule.query(
+ expr=f"rule_id in {rule_id}",
+ output_fields=["id", "zh_desc_class", "text_vector","range_value"],
+ consistency_level="Strong"
+ )
+
+ # 3. 璁$畻涓や袱鐩镐技搴�
+ results = []
+ pos_weights = {
+ ('n', 'n'): 1.0, # 鍚嶈瘝鍖归厤
+ ('v', 'v'): 0.8, # 鍔ㄨ瘝鍖归厤
+ ('n', 'v'): 0.3 # 鍚嶈瘝-鍔ㄨ瘝浜ゅ弶
+ }
+ # 寰幆缁撴灉闆�
+ for item_a in res_a:
+ if item_a["detect_num"]>0 : # 鏈夋娴嬪埌鐩爣鏃惰繘琛屾瘮瀵�
+ for item_b in res_b: # 鍜屾瘡涓鍒欓」杩涜瀵规瘮
+ similarity = 0
+ # 1. 鍚戦噺鐩镐技搴︼紙60%鏉冮噸锛�
+ # 灏嗗悜閲忚浆涓簄umpy鏁扮粍
+ vec_a = np.array(item_a["text_vector"])
+ vec_b = np.array(item_b["text_vector"])
+ assert vec_a.shape == vec_b.shape, f"缁村害涓嶅尮閰�: {vec_a.shape} vs {vec_b.shape}"
+ vec_a = vec_a.astype(np.float64) # 鎻愬崌璁$畻绮惧害
+ vec_b = vec_b.astype(np.float64)
+ # 璁$畻鐩镐技搴�
+ vector_sim = np.dot(vec_a, vec_b) / (np.linalg.norm(vec_a) * np.linalg.norm(vec_b))
+
+ # 2. 璇嶆�у尮閰嶅害锛�40%鏉冮噸锛�
+ desc_a = ast.literal_eval(item_a['zh_desc_class']) # 鑾峰彇鐩爣璇箟
+ desc_b = ast.literal_eval(item_b['zh_desc_class'])
+ for clas_a in desc_a: # 鍜屾瘡涓洰鏍囪涔夎繘琛屽姣�
+ pos_match = 0
+ for (_, pos_a, _), (_, pos_b, _) in zip(clas_a, desc_b):
+ pos_match += pos_weights.get((pos_a, pos_b), 0)
+ pos_match /= max(len(clas_a), len(desc_b))
+
+ #鎸夋潈閲嶇粍瑁� 褰撳墠鐩镐技搴� 骞惰祴鍊兼渶澶у��
+ stem_int = 0.6 * vector_sim + 0.4 * pos_match
+ if stem_int > similarity:
+ similarity = stem_int
+
+ # 3.鐩镐技搴﹀鏋滃ぇ浜庤鍒欏尮閰嶉槇鍊�,缁勮棰勮鏁版嵁
+ if similarity > item_b["range_value"]:
+ logging.info(f"鐩镐技搴︼細{similarity}锛歿item_a['zh_desc_class']} {item_b['zh_desc_class']}")
+ results.append({
+ "a_id": item_a["id"],
+ "b_id": item_b["id"],
+ "similarity": round(float(similarity), 4)
+ })
+
+ # 4. 鎸夌浉浼煎害鎺掑簭
+ if len(results) > 0:
+ comparison_results = sorted(results, key=lambda x: x["similarity"], reverse=True) # 闆嗗悎鎺掑簭
+ # 淇濆瓨褰曞儚瑙嗛
+ asyncio.run(self.video_task(video_point_id,video_image_time,"basic",frame_id,video_path,videotaskurl))
+ # 淇濆瓨鍒癿ilvus
+ self.update_milvus(image_id,res_a,1,comparison_results[0]['similarity'],rule_id)
+ else:
+ self.update_milvus(image_id,res_a,0,0.0,rule_id)
+ except Exception as e:
+ self.logger.info(f"{video_point_id}绾跨▼锛氳鍒欏姣旀椂鍑洪敊:{image_id,rule_id}锛� {e}")
+
+#鍚姩褰曞儚
+async def video_task(self,video_point_id,video_image_time,task_id,frame_id,video_path,videotaskurl):
+ try:
+ json_data = {
+ "cameraId": f"{video_point_id}",
+ "timestamp": video_image_time,
+ "preSeconds": 10,
+ "postSeconds": 10,
+ "taskId": task_id,
+ "fid": frame_id,
+ "uploadUrl": video_path,
+ "uploadType": "local"
+ }
+ self.logger.info(f"{video_point_id}绾跨▼锛氳皟鐢ㄥ綍鍍忔湇鍔�:{videotaskurl, json_data}")
+
+ # 瀹氫箟璇锋眰鐨� URL
+ # 鍙戦�� GET 璇锋眰
+ response = requests.post(videotaskurl,json=json_data,timeout=(0.03, 0.03))
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json()
+ print(data)
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿videotaskurl}锛歿e}")
+
+def update_milvus(self,image_id,res_a,is_waning,similarity,rule_id_list):
+ try:
+ # 淇濆瓨鍒癿ilvus
+ self.collection.upsert(
+ data=[{
+ "id": image_id[0],
+ "text_vector": res_a[0]["text_vector"],
+ "is_waning": is_waning,
+ "waning_value": similarity,
+ "rule_id": rule_id_list,
+ "zh_desc_class": res_a[0]['zh_desc_class'], # text_vector
+ "bounding_box": res_a[0]['bounding_box'], # bounding_box
+ "object_label": res_a[0]['object_label'], # desc
+ "task_id": res_a[0]['task_id'], # task_id
+ "event_level_id": res_a[0]['event_level_id'], # event_level_id
+ "video_point_id": res_a[0]['video_point_id'], # video_point_id
+ "detect_num": res_a[0]['detect_num'],
+ "detect_id": res_a[0]['detect_id'], # detect_id
+ "detect_time": res_a[0]['detect_time'], # detect_time
+ "image_path": res_a[0]['image_path'], # image_path
+ "video_path": res_a[0]['video_path'] # video_path
+ }]
+ )
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氳鍒欏姣斿悗淇敼鏁版嵁鏃跺嚭閿�:{image_id}锛氭槸鍚﹂璀is_waning}锛氶璀﹀�硷細{similarity}锛氳鍒檌d:{rule_id_list}:鏁版嵁闆嗗悎锛歿len(res_a)} :{e}")
+
+def tark_do(image_id,image_path,milvusurl,milvusport):
+ try :
+ # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+ qwen_tokenizer = AutoProcessor.from_pretrained("Qwen2-VL-2B", trust_remote_code=True)
+ qwen_model = AutoModelForVision2Seq.from_pretrained("Qwen2-VL-2B", device_map="auto", trust_remote_code=True).eval()
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=milvusurl, port=milvusport)
+ # 鍔犺浇闆嗗悎
+ collection = Collection(name="smartobject")
+ collection.load()
+ # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ res_a = collection.query(
+ expr=f"id == {image_id}",
+ output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+ "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id", "detect_time", "image_path", "video_path"],
+ consistency_level="Strong"
+ )
+ # 鍥剧墖鍜岃棰戝湴鍧�
+ image = Image.open(image_path) # 鏇挎崲涓烘偍鐨勫浘鐗囪矾寰�
+ image = image.thumbnail((512, 512))
+ text = "鎻忚堪杩欏紶鍥剧墖鐨勫唴瀹�"
+ # 澶勭悊杈撳叆
+ inputs = qwen_tokenizer(text=text, images=image, return_tensors="pt").to("cuda")
+ # 鐢熸垚杈撳嚭
+ with torch.no_grad():
+ outputs = qwen_model.generate(**inputs, max_new_tokens=50)
+ response = qwen_tokenizer.decode(outputs[0], skip_special_tokens=True)
+ print(response)
+
+ # 淇濆瓨鍒癿ilvus
+ collection.upsert(
+ data=[{
+ "id": image_id,
+ "text_vector": res_a[0]["text_vector"],
+ "is_waning": res_a[0]["is_waning"],
+ "waning_value": res_a[0]["waning_value"],
+ "rule_id": res_a[0]["rule_id"],
+ "zh_desc_class": res_a[0]['zh_desc_class'], # text_vector
+ "bounding_box": res_a[0]['bounding_box'], # bounding_box
+ "object_label": f"{response}", # desc
+ "task_id": res_a[0]['task_id'], # task_id
+ "event_level_id": res_a[0]['event_level_id'], # event_level_id
+ "video_point_id": res_a[0]['video_point_id'], # video_point_id
+ "detect_num": res_a[0]['detect_num'],
+ "detect_id": res_a[0]['detect_id'], # detect_id
+ "detect_time": res_a[0]['detect_time'], # detect_time
+ "image_path": res_a[0]['image_path'], # image_path
+ "video_path": res_a[0]['video_path'] # video_path
+ }]
+ )
+ print(f"鎵ц浠诲姟{image_id,image_path}锛氱粨鏉�")
+ return 1
+ except Exception as e:
+ print(f"鎵ц妯″瀷瑙f瀽鏃跺嚭閿�:{image_id,image_path} :{e}")
+ return 0
+
+
+# 绀轰緥锛氭枃鏈鐞嗘帴鍙�
+@app.route('/process', methods=['POST'])
+def process_text():
+ data = request.json
+ # 璋冪敤鎮ㄧ殑澶勭悊鍑芥暟锛堜緥濡� Qwen2-VL 妯″瀷锛�
+ try:
+ return tark_do(data.get("image_id"),data.get("image_path"),data.get("milvusurl"),data.get("milvusport")) # 鏇挎崲涓哄疄闄呭嚱鏁�
+ except Exception as e:
+ # 閿欒澶勭悊
+ return 0
+
+if __name__ == '__main__':
+ app.run(host='0.0.0.0', port=5000, debug=True)
\ No newline at end of file
diff --git a/get_mem.py b/get_mem.py
new file mode 100644
index 0000000..75752d2
--- /dev/null
+++ b/get_mem.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+SMEM Python鎺ュ彛妯″潡
+鎻愪緵瀵瑰叡浜唴瀛樺簱鐨勮闂紝鐢ㄤ簬璇诲彇鎽勫儚澶村浘鍍忓拰鍚戦噺鏁版嵁
+"""
+
+import os
+import sys
+import ctypes
+from ctypes import *
+from typing import Tuple, List, Dict, Optional, Any
+
+# 瀹氫箟閿欒鐮佸父閲�
+SMEM_SUCCESS = 0
+SMEM_ERROR_INVALID_PARAM = -1
+SMEM_ERROR_CONFIG = -2
+SMEM_ERROR_CREATE_SHM = -3
+SMEM_ERROR_NO_MEMORY = -4
+SMEM_ERROR_BUSY = -5
+SMEM_ERROR_NOT_FOUND_CAMERID = -6
+SMEM_ERROR_NOT_FOUND_FRAMEID = -7
+SMEM_ERROR_INVALID_STATE = -8
+SMEM_ERROR_INVALID_SIZE = -9
+
+
+# 瀹氫箟鍘熷瓙绫诲瀷
+class atomic_size_t(Structure):
+ _fields_ = [("__a", c_size_t)]
+
+
+class atomic_int(Structure):
+ _fields_ = [("__a", c_int)]
+
+
+# 淇ActiveCameraList缁撴瀯浣撳畾涔�
+class ActiveCameraList(Structure):
+ _fields_ = [
+ ("camera_ids_offset", c_size_t), # 鎽勫儚澶碔D鏁扮粍鐩稿鍋忕Щ閲�
+ ("count", atomic_size_t), # 褰撳墠娲诲姩鎽勫儚澶存暟閲�
+ ("capacity", atomic_size_t), # 鏁扮粍瀹归噺
+ ("lock", atomic_int) # 鐢ㄤ簬鍚屾鐨勯攣
+ ]
+
+
+# 淇ReadImageData缁撴瀯浣撳畾涔�
+class ReadImageData(Structure):
+ _fields_ = [
+ ("frame_id", c_uint64),
+ ("clock_time", c_uint64),
+ ("image_size", c_size_t),
+ ("image_data", POINTER(c_char))
+ ]
+
+
+# 鍔犺浇鍏变韩搴�
+def load_smem_library():
+ """鍔犺浇鍏变韩鍐呭瓨搴�"""
+ try:
+ # 灏濊瘯浠庝笉鍚屼綅缃姞杞藉簱
+ lib_paths = [
+ "./libsmem.so", # 褰撳墠鐩綍
+ "/lib/x86_64-linux-gnu/libsmem.so", # 绯荤粺搴撶洰褰�
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), "libsmem.so") # 妯″潡鐩綍
+ ]
+
+ for path in lib_paths:
+ if os.path.exists(path):
+ return CDLL(path)
+
+ # 濡傛灉鎵句笉鍒版寚瀹氳矾寰勶紝灏濊瘯鐩存帴鎸夊悕绉板姞杞�
+ return CDLL("libsmem.so")
+ except Exception as e:
+ print(f"鍔犺浇鍏变韩鍐呭瓨搴撳け璐�: {e}")
+ sys.exit(1)
+
+
+# 鍔犺浇搴�
+_lib = load_smem_library()
+
+# 璁剧疆鍑芥暟鍘熷瀷
+_lib.smem_init.argtypes = []
+_lib.smem_init.restype = c_int
+
+_lib.client_smem_init.argtypes = []
+_lib.client_smem_init.restype = c_int
+
+_lib.smem_destroy.argtypes = []
+_lib.smem_destroy.restype = None
+
+_lib.offset_to_ptr.argtypes = [c_size_t]
+_lib.offset_to_ptr.restype = c_void_p
+
+_lib.smem_get_camera_list.argtypes = []
+_lib.smem_get_camera_list.restype = POINTER(ActiveCameraList)
+
+# dino璇诲彇 鎽勫儚澶磇d
+_lib.smem_read_frame_dino.argtypes = [c_int64, POINTER(ReadImageData)]
+_lib.smem_read_frame_dino.restype = c_int
+
+# dino璁剧疆鍗冮棶id
+_lib.smem_set_qianwenID.argtypes = [c_int64, c_uint64, c_uint64]
+_lib.smem_set_qianwenID.restype = c_int
+
+# 鍗冮棶璇诲彇
+_lib.smem_read_frame_qianwen.argtypes = [c_int64]
+_lib.smem_read_frame_qianwen.restype = c_uint64
+
+_lib.smem_destory_frame.argtypes = [c_int64, c_uint64]
+_lib.smem_destory_frame.restype = c_int
+
+
+# Python鍖呰鍑芥暟
+def smem_init() -> int:
+ return _lib.client_smem_init()
+
+
+def get_active_cameras() -> List[int]:
+ """
+ 鑾峰彇娲诲姩鎽勫儚澶村垪琛�
+
+ Returns:
+ List[int]: 杩斿洖鎽勫儚澶碔D鍒楄〃锛屽鏋滃彂鐢熼敊璇垯杩斿洖绌哄垪琛�
+ """
+ try:
+ # 鑾峰彇鎽勫儚澶村垪琛ㄦ寚閽�
+ camera_list_ptr = _lib.smem_get_camera_list()
+ if not camera_list_ptr:
+ print("閿欒锛歴mem_get_camera_list杩斿洖绌烘寚閽�")
+ return []
+
+ # 瀹夊叏鍦拌闂粨鏋勪綋鍐呭
+ try:
+ camera_list = camera_list_ptr.contents
+ except (ValueError, AttributeError) as e:
+ print(f"閿欒锛氭棤娉曡闂憚鍍忓ご鍒楄〃鍐呭: {e}")
+ return []
+
+ # 鑾峰彇鎽勫儚澶存暟閲�
+ try:
+ count = camera_list.count.__a
+ if count < 0 or count > 1000: # 璺宠繃鏃犳晥鏁伴噺
+ print(f"閿欒锛氭棤鏁堢殑鎽勫儚澶存暟閲�: {count}")
+ return []
+ except AttributeError as e:
+ print(f"閿欒锛氭棤娉曡闂甤ount瀛楁: {e}")
+ return []
+
+ # 鑾峰彇camera_ids鏁扮粍鎸囬拡
+ camera_ids_ptr = _lib.offset_to_ptr(camera_list.camera_ids_offset)
+ if not camera_ids_ptr:
+ print("閿欒锛氭棤娉曡幏鍙朿amera_ids鏁扮粍鎸囬拡")
+ return []
+
+ # 杞崲涓篜ython鍒楄〃
+ camera_ids = cast(camera_ids_ptr, POINTER(c_int64))
+ result = []
+ for i in range(count):
+ try:
+ camera_id = camera_ids[i]
+ if camera_id != -1: # 璺宠繃鏃犳晥ID
+ result.append(camera_id)
+ except (IndexError, ValueError) as e:
+ print(f"璀﹀憡锛氳闂储寮晎i}鏃跺嚭閿�: {e}")
+ continue
+
+ return result
+
+ except Exception as e:
+ print(f"閿欒锛氳幏鍙栨憚鍍忓ご鍒楄〃鏃跺彂鐢熷紓甯�: {e}")
+ return []
+
+
+def smem_read_frame_image_dino(camera_id: int) -> Tuple[int, Dict[str, Any]]:
+ """
+ 璇诲彇鎸囧畾鎽勫儚澶寸殑鏈�灏忓抚鍙峰浘鍍忔暟鎹�
+
+ Args:
+ camera_id: 鎽勫儚澶碔D
+
+ Returns:
+ (鐘舵�佺爜, 鍥惧儚鏁版嵁瀛楀吀)
+ """
+ # 鍒涘缓杈撳嚭缁撴瀯浣�
+ read_data = ReadImageData()
+
+ # 璋冪敤C鍑芥暟
+ status = _lib.smem_read_frame_dino(camera_id, byref(read_data))
+
+ # 澶勭悊缁撴灉
+ if status == SMEM_SUCCESS:
+ # 鍙鍒跺疄闄呬娇鐢ㄧ殑鏁版嵁閮ㄥ垎
+ actual_data = bytes(read_data.image_data[:read_data.image_size])
+ result = {
+ "frame_id": read_data.frame_id,
+ "clock_time": read_data.clock_time,
+ "image_size": read_data.image_size,
+ "image_data": actual_data
+ }
+ else:
+ result = {
+ "error": f"璇诲彇澶辫触锛岄敊璇爜: {status}"
+ }
+
+ return status, result
+
+
+def smem_set_qianwen_id(camera_id: int, frame_Id: int, qianwen_id: int) -> int:
+ """
+ 璁剧疆鎸囧畾鎽勫儚澶寸殑鍗冮棶ID
+
+ Args:
+ camera_id: 鎽勫儚澶碔D
+ frame_id: 甯d
+ qianwenID: 鍗冮棶id
+ Returns:
+ 鐘舵�佺爜
+ """
+ return _lib.smem_set_qianwenID(camera_id, frame_Id, qianwen_id)
+
+
+def smem_read_frame_qianwen(camera_id: int) -> int:
+ """
+ 璇诲彇鎸囧畾鎽勫儚澶寸殑鍗冮棶ID
+
+ Args:
+ camera_id: 鎽勫儚澶碔D
+
+ Returns:
+ 鎴愬姛鏃惰繑鍥炲崈闂甀D锛堥潪璐熷�硷級锛屽け璐ユ椂杩斿洖閿欒鐮侊紙璐熷�硷級
+ """
+ # 璋冪敤C鍑芥暟锛岃繑鍥炲�煎皬浜�0琛ㄧず閿欒锛屽ぇ浜庣瓑浜�0琛ㄧず鎴愬姛骞朵笖璇ュ�煎氨鏄痲ianwenID
+ result = _lib.smem_read_frame_qianwen(camera_id)
+ return result
+
+
+def smem_destory_frame_image(camera_id: int, frame_id: int) -> int:
+ """
+ 閿�姣佹寚瀹氭憚鍍忓ご鐨勬寚瀹氬抚鍙峰浘鍍忔暟鎹�
+
+ Args:
+ camera_id: 鎽勫儚澶碔D
+ frame_id: 甯у彿
+
+ Returns:
+ 鐘舵�佺爜
+ """
+ return _lib.smem_destory_frame(camera_id, frame_id)
+
+
+# 閿欒鐮佽浆鎹负鍙瀛楃涓�
+def smem_error_to_string(error_code: int) -> str:
+ """
+ 灏嗛敊璇爜杞崲涓哄彲璇诲瓧绗︿覆
+
+ Args:
+ error_code: 閿欒鐮�
+
+ Returns:
+ 閿欒鎻忚堪瀛楃涓�
+ """
+ error_map = {
+ SMEM_SUCCESS: "鎴愬姛",
+ SMEM_ERROR_INVALID_PARAM: "鏃犳晥鍙傛暟",
+ SMEM_ERROR_CONFIG: "閰嶇疆閿欒",
+ SMEM_ERROR_CREATE_SHM: "鍒涘缓鍏变韩鍐呭瓨澶辫触",
+ SMEM_ERROR_NO_MEMORY: "鍐呭瓨涓嶈冻",
+ SMEM_ERROR_BUSY: "璧勬簮蹇�",
+ SMEM_ERROR_NOT_FOUND_CAMERID: "鏈壘鍒版憚鍍忓ご",
+ SMEM_ERROR_NOT_FOUND_FRAMEID: "鏈壘鍒板抚鍙�",
+ SMEM_ERROR_INVALID_STATE: "鏃犳晥鐘舵��",
+ SMEM_ERROR_INVALID_SIZE: "鏃犳晥澶у皬"
+ }
+ return error_map.get(error_code, f"鏈煡閿欒 ({error_code})")
+
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+ # 鍒濆鍖栧叡浜唴瀛�
+ status = smem_init()
+ if status != SMEM_SUCCESS:
+ print(f"python---鍒濆鍖栧け璐�: {smem_error_to_string(status)}")
+ sys.exit(1)
+
+ print("python---鍒濆鍖栨垚鍔�")
+
+ try:
+ # 鑾峰彇鎽勫儚澶村垪琛�
+ camera_list = get_active_cameras()
+ print(f"python---鍙戠幇 {len(camera_list)} 涓椿鍔ㄦ憚鍍忓ご")
+
+ for camera_id in camera_list:
+ # print(f"鎽勫儚澶碔D: {camera_id}")
+
+ # 璇诲彇鍥惧儚鏁版嵁
+ status, image_data = smem_read_frame_image_dino(camera_id)
+ if status == SMEM_SUCCESS:
+ image_size = image_data["image_size"]
+ print(f" python---dino---------------------璇诲彇鎴愬姛:")
+ print(f" python---dino--甯у彿: {image_data['frame_id']}")
+ print(f" python---dino--澶у皬: {image_data['image_size']} 瀛楄妭")
+ print(f" python---dino--鏃堕棿鎴�: {image_data['clock_time']}")
+ # print(f" dino--鏁版嵁: {image_data['image_data']}")
+ qianwenID = camera_id * 10 + 111
+ aframdid = image_data["frame_id"]
+ print(f" python---璁剧疆褰撳墠 鍗冮棶 ID: {qianwenID} 褰撳墠甯ф槸ID: {aframdid} ,鍗冮棶璇诲彇..")
+ smem_set_qianwen_id(camera_id, aframdid, qianwenID)
+ status1 = smem_read_frame_qianwen(camera_id)
+ if status1 > 0:
+ print(f" python---qianwen----------------------璇诲彇鎴愬姛:")
+ print(f" python---qianwen--鍗冮棶ID: {status1}")
+ else:
+ print(f"python---qianwen璇诲彇澶辫触: {smem_error_to_string(status1)}")
+ else:
+ print(f"python---璇诲彇鍥惧儚澶辫触: {smem_error_to_string(status)}")
+
+ finally:
+ print("python---鎿嶄綔瀹屾垚")
\ No newline at end of file
diff --git a/int.txt b/int.txt
new file mode 100644
index 0000000..2929776
--- /dev/null
+++ b/int.txt
@@ -0,0 +1,33 @@
+pip install numpy==1.26.4 timm==0.6.13 ninja pymilvus supervision jieba sentencepiece peft==0.7.1 auto-gptq accelerate transformers_stream_generator tiktoken einops optimum
+pip install torch==2.1.2+cu118 torchvision==0.16.2+cu118 --index-url https://download.pytorch.org/whl/cu118
+pip install transformers==4.51.0 bitsandbytes==0.44.0 accelerate==0.27.0
+
+
+[Unit]
+Description= dinoapp
+After=network.target
+
+
+[Service]
+User=root
+Group=root
+Environment="PATH=/root/anaconda3/envs/smartenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+ExecStart=/root/anaconda3/envs/smartenv/bin/python /home/basic/dino/dinostart.py
+WorkingDirectory=/home/basic/dino
+
+Restart=always
+RestartSec=10
+StandardOutput=syslog
+StandardError=syslog
+
+[Install]
+WantedBy=multi-user.target
+
+# 閲嶆柊鍔犺浇Systemd閰嶇疆
+sudo systemctl daemon-reload
+
+# 鍚敤寮�鏈鸿嚜鍚�
+sudo systemctl enable my_python_app.service
+
+# 绔嬪嵆鍚姩鏈嶅姟
+sudo systemctl start my_python_app.service
\ No newline at end of file
diff --git a/qwen_detect.py b/qwen_detect.py
new file mode 100644
index 0000000..db6ccea
--- /dev/null
+++ b/qwen_detect.py
@@ -0,0 +1,234 @@
+# 绂佺敤tokenizer骞惰锛堝繀椤绘斁鍦ㄦ墍鏈塱mport涔嬪墠锛�
+import torch
+import threading
+import time as time_sel
+from typing import Dict
+import qwen_task
+import requests
+import os
+
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+ def __init__(self):
+ #璇诲彇閰嶇疆鏂囦欢
+ self.config = {}
+ with open('./conf.txt', 'r', encoding='utf-8') as file:
+ for line in file:
+ # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+ line = line.strip()
+ # 璺宠繃绌鸿
+ if not line:
+ continue
+ # 鍒嗗壊閿拰鍊�
+ if '=' in line:
+ key, value = line.split('=', 1)
+ # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+ key = key.strip()
+ value = value.strip()
+ # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+ self.config[key] = value
+ # 閰嶇疆鏃ュ織
+ # 纭繚鏃ュ織鐩綍瀛樺湪
+ log_dir = "logs"
+ os.makedirs(log_dir, exist_ok=True)
+ self.threads: Dict[str, threading.Thread] = {}
+ self.lock = threading.Lock()
+
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
+
+ # 鍒濆鍖杚wenvl妫�娴嬫ā鍨�
+ self.qwen_model = AutoModelForVision2Seq.from_pretrained(
+ "./Qwen2-VL-2B-Instruct", device_map="auto",
+ trust_remote_code=True,
+ torch_dtype=torch.float16
+ )
+
+ # default processer
+ self.qwen_tokenizer = AutoProcessor.from_pretrained("./Qwen2-VL-2B-Instruct")
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+ # 鍔犺浇闆嗗悎
+ self.collection = Collection(name="smartobject")
+ self.collection.load()
+
+ #鏄惁鏇存柊
+ self._isupdate = False
+
+ # 鍒濆鍖栧叡浜唴瀛�
+ get_mem.smem_init()
+
+ # 閰嶇疆鏃ュ織
+ logging.basicConfig(
+ level=logging.INFO,
+ format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S',
+ handlers=[
+ # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+ RotatingFileHandler(
+ filename=os.path.join(log_dir, 'start_log.log'),
+ maxBytes=10 * 1024 * 1024, # 10MB
+ backupCount=3,
+ encoding='utf-8'
+ ),
+ # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+ logging.StreamHandler()
+ ]
+ )
+
+ #鍚姩绾跨▼
+ def safe_start(self, target_func, camera_id):
+ """绾跨▼瀹夊叏鍚姩鏂规硶"""
+ def wrapped():
+ thread_name = threading.current_thread().name
+ try:
+ target_func(camera_id)
+ except Exception as e:
+ logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+ with self.lock: # 纭繚绾跨▼瀹夊叏鍒涘缓
+ t = threading.Thread(
+ target=wrapped,
+ daemon=True # 璁剧疆涓哄畧鎶ょ嚎绋�
+ )
+ t.start()
+ self.threads[camera_id] = t
+ return t
+
+ # 鍚姩绾跨▼浠诲姟
+ def worker(self, camera_id):
+ # 鍒濆鍖�
+ detect = qwen_task.detect_tasks()
+ detect._thread_name = f"{camera_id}" # 璁剧疆鍚嶇О
+ detect.init_logging(f"{camera_id}")
+ # 鍒濆鍖栨娴嬫ā鍨�
+ detect.device = self.device
+ # 鍒濆鍖杚wen妯″瀷
+ detect.qwen_tokenizer = self.qwen_tokenizer
+ detect.qwen_model = self.qwen_model
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ detect.collection = self.collection
+
+ # 璁剧疆绾跨▼鍚姩鐘舵��
+ detect._running = True
+ while True:
+ try:
+ # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+ image_id = get_mem.smem_read_frame_qianwen(camera_id)
+ if image_id > 0:
+ logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+ image_id = detect.tark_do(image_id,self.config.get("filesavepath"),self.config.get("ragurl"),self.config.get("max_tokens"))
+ logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+ except Exception as e:
+ logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+ #璋冪敤鏄惁闇�瑕佹洿鏂�
+ def isUpdate(self):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("isupdateurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json().get("data")
+ if data.get("isChange") == 1:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+ return False
+
+ #淇敼鏄惁鏇存柊鐘舵��
+ def update_status(self):
+ try:
+ # 鏇存柊鐘舵��
+ url = self.config.get("updatestatusurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.post(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+ return False
+
+ def shutdown_all(self) -> None:
+ """娓呯悊鎵�鏈夌嚎绋�"""
+ with self.lock:
+ for camera_id, thread in list(self.threads.items()):
+ if thread.is_alive():
+ thread.join(timeout=1)
+ del self.threads[camera_id]
+
+ #鑾峰彇浠诲姟
+ def getTaskconf(self,isupdate):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("gettaskconfurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json()
+ if isupdate:
+ # 鏇存柊鐘舵��
+ self.update_status()
+ return data.get("data")
+ else:
+ return []
+ except Exception as e:
+ logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+ return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+ pool = ThreadPool()
+ is_init = True
+ camera_data = pool.getTaskconf(False)
+ while True:
+ try:
+ pool._isupdate = False # 鏄惁鏇存柊鏁版嵁
+ # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+ if pool.isUpdate():
+ # 鑾峰彇鎽勫儚鏈轰换鍔�
+ camera_data = pool.getTaskconf(True)
+ pool._isupdate = True # 鏇存柊鏁版嵁
+
+ if is_init:
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ if pool._isupdate:
+ logging.info(f"鏇存柊绾跨▼寮�濮�")
+ pool.shutdown_all()
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+ is_init = False
+ time_sel.sleep(1)
+ except Exception as e:
+ logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/qwen_ollama.py b/qwen_ollama.py
new file mode 100644
index 0000000..92a197a
--- /dev/null
+++ b/qwen_ollama.py
@@ -0,0 +1,332 @@
+import asyncio
+import base64
+import io
+import json
+import os
+import re
+
+import requests
+import torch
+import logging
+from PIL import Image
+from logging.handlers import RotatingFileHandler
+
+
+class detect_tasks():
+ def __init__(self):
+ # 绾跨▼鍚嶇О
+ self._thread_name = ''
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ self.collection = None
+
+ def remove_duplicate_lines(self, text):
+
+ seen = set()
+ result = []
+ for line in text.split('銆�'): # 鎸夊彞鍙峰垎鍓�
+ if line.strip() and line not in seen:
+ seen.add(line)
+ result.append(line)
+ return '銆�'.join(result)
+
+ def remove_duplicate_lines_d(self, text):
+ seen = set()
+ result = []
+ for line in text.split(','): # 鎸夊彞鍙峰垎鍓�
+ if line.strip() and line not in seen:
+ seen.add(line)
+ result.append(line)
+ return '銆�'.join(result)
+
+ def remove_duplicate_lines_n(self, text):
+ seen = set()
+ result = []
+ for line in text.split('\n'): # 鎸夊彞鍙峰垎鍓�
+ if line.strip() and line not in seen:
+ seen.add(line)
+ result.append(line)
+ return '銆�'.join(result)
+
+ def init_logging(self, logname):
+ # 鍒涘缓瀹炰緥涓撳睘logger
+ self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+ self.logger.setLevel(logging.INFO)
+ # 閬垮厤閲嶅娣诲姞handler
+ if not self.logger.handlers:
+ handler = RotatingFileHandler(
+ filename=os.path.join("logs", logname + '_log.log'),
+ maxBytes=10 * 1024 * 1024,
+ backupCount=3,
+ encoding='utf-8'
+ )
+ formatter = logging.Formatter(
+ '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+ )
+ handler.setFormatter(formatter)
+ self.logger.addHandler(handler)
+
+ def image_desc(self, image_path, ollama_url, ollama_mode="qwen2.5vl:3b"):
+ try:
+ image_des = None
+ # 鍥剧墖棰勫鐞�
+ img = Image.open(image_path)
+ buffered = io.BytesIO()
+ img.save(buffered, format="JPEG", quality=85)
+ img_str = base64.b64encode(buffered.getvalue()).decode('utf-8')
+ # 璋冪敤API
+ response = requests.post(
+ f"{ollama_url}/api/generate",
+ json={
+ "model": ollama_mode,
+ "prompt": "璇锋寜浠ヤ笅瑕佹眰鎻忚堪鍥剧墖锛歕n1. 鍒楀嚭涓昏鐗╀綋\n2.涓嶈繘琛屾帹鐞嗗拰think\n杩斿洖灏忎簬2000瀛楃殑鏁存鎻忚堪,鎻忚堪涓殑鐗╀綋淇℃伅涓嶅姞鏁板瓧搴忓彿",
+ "images": [img_str],
+ "options": {
+ "num_gpu_layers": 35
+ },
+ "stream": False # 闈炴祦寮�
+ },
+ headers={"Content-Type": "application/json"}
+ )
+ result = response.json()
+ if result and result["response"]:
+ image_des = (result["response"]).replace('\n', '')
+ if len(image_des) > 4 and image_des.startswith("杩欏紶鍥剧墖"):
+ image_des = image_des[4:]
+
+ image_des = self.remove_duplicate_lines(image_des)
+ image_des = self.remove_duplicate_lines_d(image_des)
+ image_des = self.remove_duplicate_lines_n(image_des)
+ # self.logger.info(image_des)
+ else:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path, result, response}")
+ return image_des
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path, e}")
+ return None
+
+ def get_rule(self, ragurl):
+ try:
+ rule_text = None
+ search_data = {
+ "collection_name": "smart_rule",
+ "query_text": "",
+ "search_mode": "hybrid",
+ "limit": 100,
+ "weight_dense": 0.7,
+ "weight_sparse": 0.3,
+ "filter_expr": "",
+ "output_fields": ["text"]
+ }
+ response = requests.post(ragurl + "/search", json=search_data)
+ results = response.json().get('results')
+ rule_text = ""
+ ruleid = 1
+ for rule in results:
+ if rule['score'] >= 0:
+ rule_text = rule_text + str(ruleid) + ". " + rule['entity'].get('text') + ";\n"
+ ruleid = ruleid + 1
+ # self.logger.info(len(rule_text))
+ else:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{response}")
+ return rule_text
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{e}")
+ return None
+
+ def image_rule_chat(self, image_des, rule_text, ollama_url, ollama_mode="qwen2.5vl:3b"):
+ try:
+ is_waning = 0
+
+ # 璇锋眰鍐呭
+ content = (
+ f"鍥剧墖鎻忚堪鍐呭涓猴細\n{image_des}\n瑙勫垯鍐呭锛歕n{rule_text}銆俓n璇烽獙璇佸浘鐗囨弿杩颁腑鏄惁鏈夌鍚堣鍒欑殑鍐呭锛屼笉杩涜鎺ㄧ悊鍜宼hink銆傝繑鍥炵粨鏋滄牸寮忎负[xxx绗﹀悎鐨勮鍒檌d]锛屽鏋滄病鏈夎繑鍥瀃]")
+
+ # API璋冪敤
+ response = requests.post(
+ # ollama鍦板潃
+ url=f"{ollama_url}/api/chat",
+ json={
+ # 榛樿妯″瀷
+ "model": ollama_mode,
+ "messages": [
+ {"role": "user", "content": content}
+ ],
+ "stream": False # 鍏抽棴娴佸紡杈撳嚭
+ }
+ )
+ # 缁撴灉澶勭悊
+ ret = response.json()["message"]["content"]
+ if len(ret) > 2:
+ is_waning = 1
+ # self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃鍒欏尮閰嶆椂鍑洪敊:{image_des, rule_text,ret, response, ollama_url, ollama_mode}")
+ return is_waning
+ except Exception as e:
+ self.logger.info(
+ f"{self._thread_name}绾跨▼锛氭墽琛岃鍒欏尮閰嶆椂鍑洪敊:{image_des, rule_text, ollama_url, ollama_mode, e}")
+ return None
+
+ # 闅愭偅鎻忚堪
+ def image_rule_chat_with_detail(self,filedata, rule_text, ollama_url, ollama_mode="qwen2.5vl:3b"):
+
+ # API璋冪敤
+ response = requests.post(
+ # ollama鍦板潃
+ url=f"{ollama_url}/chat",
+ json={
+ "prompt":"",
+ # 璇锋眰鍐呭
+ "messages": [
+ {
+ "role": "user",
+ "content": f"璇锋牴鎹绔犲埗搴{filedata}]\n鏌ユ壘[{rule_text}]鐨勫畨鍏ㄩ殣鎮f弿杩帮紝涓嶈繘琛屾帹鐞嗗拰think銆傝繑鍥炰俊鎭皬浜�800瀛�"
+ }
+ ],
+ # 鎸囧畾妯″瀷
+ "llm_name": "qwen3:8b",
+ "stream": False, # 鍏抽棴娴佸紡杈撳嚭
+ "gen_conf": {
+ "temperature": 0.7, # 鎺у埗鐢熸垚闅忔満鎬�
+ "max_tokens": 800 # 鏈�澶ц緭鍑洪暱搴�
+ }
+ }
+ )
+ # 浠巎son鎻愬彇data瀛楁鍐呭
+ ret = response.json()["data"]
+ # 绉婚櫎<think>鏍囩鍜屽唴瀹�
+ ret = re.sub(r'<think>.*?</think>', '', ret, flags=re.DOTALL)
+ # 瀛楃涓叉竻鐞�,绉婚櫎绌烘牸,鍒惰〃绗�,鎹㈣绗�,鏄熷彿
+ ret = ret.replace(" ", "").replace("\t", "").replace("\n", "").replace("**","")
+ print(ret)
+ return ret
+ #澶勭悊寤鸿
+ def image_rule_chat_suggestion(self, rule_text, ollama_url, ollama_mode="qwen2.5vl:3b"):
+ self.logger.info("----------------------------------------------------------------")
+ content = (
+ f"璇锋牴鎹繚瑙勫唴瀹筟{rule_text}]\n杩涜杩斿洖澶勭悊杩濊寤鸿锛屼笉杩涜鎺ㄧ悊鍜宼hink銆傝繑鍥炵簿鍑嗕俊鎭�")
+ response = requests.post(
+ url=f"{ollama_url}/chat",
+ json={
+
+ "llm_name": "qwen3:8b",
+ "messages": [
+ {"role": "user", "content": content}
+ ],
+ "stream": False # 鍏抽棴娴佸紡杈撳嚭
+ }
+ )
+ ret = response.json()["data"]
+ ret = re.sub(r'<think>.*?</think>', '', ret, flags=re.DOTALL)
+ ret = ret.replace(" ", "").replace("\t", "").replace("\n", "").replace("**","")
+ print(ret)
+ return ret
+
+ # print(response.json())
+ # ret = response.json()["detail"]
+
+ def get_filedata(self, searchtext, ragurl):
+ search_data = {
+ "collection_name": "smart_knowledge",
+ "query_text": searchtext,
+ "search_mode": "hybrid",
+ "limit": 100,
+ "weight_dense": 0.7,
+ "weight_sparse": 0.3,
+ "filter_expr": "",
+ "output_fields": ["text"]
+ }
+ response = requests.post(ragurl + "/search", json=search_data)
+ results = response.json().get('results')
+ text = ""
+ for rule in results:
+ text = text + rule['entity'].get('text') + ";\n"
+
+ return text
+
+ async def insert_json_data(self, ragurl, data):
+ try:
+ data = {'collection_name': "smartrag", "data": data, "description": ""}
+ requests.post(ragurl + "/insert_json_data", json=data, timeout=(0.3, 0.3))
+ # self.logger.info(f"璋冪敤褰曞儚鏈嶅姟:{ragurl, data}")
+ except Exception as e:
+ # self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿ragurl}锛歿e}")
+ return
+
+ def tark_do(self, image_id, ollamaurl, ragurl, ollamamode, ragmode):
+ try:
+ # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ is_waning = 0
+ res_a = self.collection.query(
+ expr=f"id == 458942504686042840",
+ output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+ "task_name", "event_level_id", "event_level_name",
+ "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id",
+ "detect_time", "image_path", "image_desc_path", "video_path","risk_description","suggestion","knowledge_id"],
+ consistency_level="Strong"
+ )
+
+ if not res_a:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭湭鎵惧埌ID涓� {image_id} 鐨勮褰�")
+ return 0
+
+
+ image_des = self.image_desc(f"/opt/smart/img/1748763385.245874.jpg", ollamaurl, ollamamode)
+ risk_description = ""
+ suggestion = ""
+ if image_des:
+ is_waning = self.image_rule_chat(image_des, res_a[0]['waning_value'], ollamaurl, ollamamode)
+
+ if is_waning == 0:
+
+ filedata = self.get_filedata(res_a[0]['waning_value'], ragurl)
+ risk_description = self.image_rule_chat_with_detail(filedata,res_a[0]['waning_value'], ragurl, ragmode)
+ suggestion = self.image_rule_chat_suggestion(res_a[0]['waning_value'], ragurl, ragmode)
+
+ # 鏁版嵁缁�
+ data = {
+ "id": image_id,
+ "event_level_id": res_a[0]['event_level_id'], # event_level_id
+ "event_level_name": res_a[0]['event_level_name'], # event_level_id
+ "rule_id": res_a[0]["rule_id"],
+ "video_point_id": res_a[0]['video_point_id'], # video_point_id
+ "video_point_name": res_a[0]['video_point_name'],
+ "is_waning": is_waning,
+ "zh_desc_class": image_des, # text_vector
+ "bounding_box": res_a[0]['bounding_box'], # bounding_box
+ "task_id": res_a[0]['task_id'], # task_id
+ "task_name": res_a[0]['task_name'], # task_id
+ "detect_id": res_a[0]['detect_id'], # detect_id
+ "detect_time": res_a[0]['detect_time'], # detect_time
+ "detect_num": res_a[0]['detect_num'],
+ "waning_value": res_a[0]['waning_value'],
+ "image_path": res_a[0]['image_path'], # image_path
+ "image_desc_path": res_a[0]['image_desc_path'], # image_desc_path
+ "video_path": res_a[0]['video_path'],
+ "text_vector": res_a[0]['text_vector'],
+ "risk_description": risk_description,
+ "suggestion": suggestion,
+ "knowledge_id": res_a[0]['knowledge_id']
+ }
+
+
+
+ # 淇濆瓨鍒癿ilvus
+ image_id = self.collection.upsert(data).primary_keys
+ data = {
+ "id": str(image_id[0]),
+ "video_point_id": res_a[0]['video_point_id'],
+ "video_path": res_a[0]["video_point_name"],
+ "zh_desc_class": image_des,
+ "detect_time": res_a[0]['detect_time'],
+ "image_path": f"{res_a[0]['image_path']}",
+ "task_name": res_a[0]["task_name"],
+ "event_level_name": res_a[0]["event_level_name"],
+ "rtsp_address": f"{res_a[0]['video_path']}"
+ }
+ # 璋冪敤rag
+ asyncio.run(self.insert_json_data(ragurl, data))
+ return image_id
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屾ā鍨嬭В鏋愭椂鍑洪敊:浠诲姟锛歿image_id} :{e}")
+ return 0
+
diff --git a/qwen_ollama_detect.py b/qwen_ollama_detect.py
new file mode 100644
index 0000000..df78f7d
--- /dev/null
+++ b/qwen_ollama_detect.py
@@ -0,0 +1,219 @@
+# 绂佺敤tokenizer骞惰锛堝繀椤绘斁鍦ㄦ墍鏈塱mport涔嬪墠锛�
+import torch
+import threading
+import time as time_sel
+from typing import Dict
+
+import qwen_ollama
+import requests
+import os
+
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+
+
+class ThreadPool:
+ def __init__(self):
+ # 璇诲彇閰嶇疆鏂囦欢
+ self.config = {}
+ with open('./conf.txt', 'r', encoding='utf-8') as file:
+ for line in file:
+ # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+ line = line.strip()
+ # 璺宠繃绌鸿
+ if not line:
+ continue
+ # 鍒嗗壊閿拰鍊�
+ if '=' in line:
+ key, value = line.split('=', 1)
+ # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+ key = key.strip()
+ value = value.strip()
+ # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+ self.config[key] = value
+ # 閰嶇疆鏃ュ織
+ # 纭繚鏃ュ織鐩綍瀛樺湪
+ log_dir = "logs"
+ os.makedirs(log_dir, exist_ok=True)
+ self.threads: Dict[str, threading.Thread] = {}
+ self.lock = threading.Lock()
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+ # 鍔犺浇闆嗗悎
+ self.collection = Collection(name="smartobject")
+ self.collection.load()
+
+ # 鏄惁鏇存柊
+ self._isupdate = False
+
+ # 鍒濆鍖栧叡浜唴瀛�
+ get_mem.smem_init()
+
+ # 閰嶇疆鏃ュ織
+ logging.basicConfig(
+ level=logging.INFO,
+ format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S',
+ handlers=[
+ # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+ RotatingFileHandler(
+ filename=os.path.join(log_dir, 'start_log.log'),
+ maxBytes=10 * 1024 * 1024, # 10MB
+ backupCount=3,
+ encoding='utf-8'
+ ),
+ # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+ logging.StreamHandler()
+ ]
+ )
+
+ # 鍚姩绾跨▼
+ def safe_start(self, target_func, camera_id):
+ """绾跨▼瀹夊叏鍚姩鏂规硶"""
+
+ def wrapped():
+ thread_name = threading.current_thread().name
+ try:
+ target_func(camera_id)
+ except Exception as e:
+ logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+ with self.lock: # 纭繚绾跨▼瀹夊叏鍒涘缓
+ t = threading.Thread(
+ target=wrapped,
+ daemon=True # 璁剧疆涓哄畧鎶ょ嚎绋�
+ )
+ t.start()
+ self.threads[camera_id] = t
+ return t
+
+ # 鍚姩绾跨▼浠诲姟
+ def worker(self, camera_id):
+ # 鍒濆鍖�
+ detect = qwen_ollama.detect_tasks()
+ detect._thread_name = f"{camera_id}" # 璁剧疆鍚嶇О
+ detect.init_logging(f"{camera_id}")
+ # 鍒濆鍖朚ilvus闆嗗悎
+ detect.collection = self.collection
+
+ while True:
+ try:
+ # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+ # image_id = get_mem.smem_read_frame_qianwen(camera_id)
+ # if image_id > 0:
+ # logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+
+ image_id = detect.tark_do(458942504686042840, self.config.get("ollamaurl"), self.config.get("ragurl"),
+ self.config.get("ollamamode"), self.config.get("ragmode"))
+ logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+ except Exception as e:
+ logging.info(f"{detect._thread_name}绾跨▼閿欒:{e}")
+
+ # 璋冪敤鏄惁闇�瑕佹洿鏂�
+ def isUpdate(self):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("isupdateurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json().get("data")
+ if data.get("isChange") == 1:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+ return False
+
+ # 淇敼鏄惁鏇存柊鐘舵��
+ def update_status(self):
+ try:
+ # 鏇存柊鐘舵��
+ url = self.config.get("updatestatusurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.post(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+ return False
+
+ def shutdown_all(self) -> None:
+ """娓呯悊鎵�鏈夌嚎绋�"""
+ with self.lock:
+ for camera_id, thread in list(self.threads.items()):
+ if thread.is_alive():
+ thread.join(timeout=1)
+ del self.threads[camera_id]
+
+ # 鑾峰彇浠诲姟
+ def getTaskconf(self, isupdate):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("gettaskconfurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json()
+ if isupdate:
+ # 鏇存柊鐘舵��
+ self.update_status()
+ return data.get("data")
+ else:
+ return []
+ except Exception as e:
+ logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+ return []
+
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+ pool = ThreadPool()
+ is_init = True
+ camera_data = pool.getTaskconf(False)
+ while True:
+ try:
+ pool._isupdate = False # 鏄惁鏇存柊鏁版嵁
+ # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+ if pool.isUpdate():
+ # 鑾峰彇鎽勫儚鏈轰换鍔�
+ camera_data = pool.getTaskconf(True)
+ pool._isupdate = True # 鏇存柊鏁版嵁
+
+ if is_init:
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ if pool._isupdate:
+ logging.info(f"鏇存柊绾跨▼寮�濮�")
+ pool.shutdown_all()
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+ is_init = False
+ time_sel.sleep(1)
+ except Exception as e:
+ logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/qwen_task.py b/qwen_task.py
new file mode 100644
index 0000000..1180264
--- /dev/null
+++ b/qwen_task.py
@@ -0,0 +1,150 @@
+import json
+import os
+import re
+
+import requests
+import torch
+import logging
+from PIL import Image
+from logging.handlers import RotatingFileHandler
+
+class detect_tasks():
+ def __init__(self):
+ #绾跨▼鍚嶇О
+ self._thread_name = ''
+ self.device = None
+ # 鍒濆鍖栨娴嬫ā鍨�
+ self.qwen_tokenizer = None
+ self.qwen_model = None
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ self.collection = None
+
+ def remove_duplicate_lines(self,text):
+ seen = set()
+ result = []
+ for line in text.split('銆�'): # 鎸夊彞鍙峰垎鍓�
+ if line.strip() and line not in seen:
+ seen.add(line)
+ result.append(line)
+ return '銆�'.join(result)
+
+ def init_logging(self,logname):
+ # 鍒涘缓瀹炰緥涓撳睘logger
+ self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+ self.logger.setLevel(logging.INFO)
+ # 閬垮厤閲嶅娣诲姞handler
+ if not self.logger.handlers:
+ handler = RotatingFileHandler(
+ filename=os.path.join("logs", logname+'_log.log'),
+ maxBytes=10 * 1024 * 1024,
+ backupCount=3,
+ encoding='utf-8'
+ )
+ formatter = logging.Formatter(
+ '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+ )
+ handler.setFormatter(formatter)
+ self.logger.addHandler(handler)
+
+ def tark_do(self,image_id,filesavepath,ragurl,max_tokens):
+ try :
+ # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ res_a = self.collection.query(
+ expr=f"id == {image_id}",
+ output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+ "task_name","event_level_id","event_level_name",
+ "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id",
+ "detect_time", "image_path", "image_desc_path","video_path"],
+ consistency_level="Strong"
+ )
+ # 鍥剧墖鍜岃棰戝湴鍧�
+ image = Image.open(f"{res_a[0]['image_desc_path']}").convert("RGB") # 鏇挎崲涓烘偍鐨勫浘鐗囪矾寰�
+ conversation = [
+ {
+ "role": "user",
+ "content": [
+ {
+ "type": "image",
+ },
+ {"type": "text", "text": "璇锋寜浠ヤ笅瑕佹眰鎻忚堪鍥剧墖锛歕n1. 鍒楀嚭涓昏鐗╀綋\n2.涓嶈繘琛屾帹鐞嗗拰think\n杩斿洖灏忎簬2000瀛楃殑鏁存鎻忚堪,鎻忚堪涓殑鐗╀綋淇℃伅涓嶅姞鏁板瓧搴忓彿"},
+ ],
+ }
+ ]
+
+ # Preprocess the inputs
+ self.logger.info("aaaa")
+ text_prompt = self.qwen_tokenizer.apply_chat_template(conversation, add_generation_prompt=True)
+ # Excepted output: '<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n<|vision_start|><|image_pad|><|vision_end|>Describe this image.<|im_end|>\n<|im_start|>assistant\n'
+ self.logger.info("bbbb")
+ inputs = self.qwen_tokenizer(
+ text=[text_prompt], images=[image], padding=True, return_tensors="pt"
+ )
+ inputs = inputs.to("cuda")
+ self.logger.info("cccc")
+ torch.cuda.empty_cache()
+ with torch.no_grad():
+ output_ids = self.qwen_model.generate(**inputs, max_new_tokens=50)
+ print(output_ids.device)
+ self.logger.info("dddd")
+ generated_ids = [
+ output_ids[len(input_ids):]
+ for input_ids, output_ids in zip(inputs.input_ids, output_ids)
+ ]
+ image_text = self.qwen_tokenizer.batch_decode(
+ generated_ids, skip_special_tokens=True, clean_up_tokenization_spaces=True
+ )
+ self.logger.info("ffff")
+ image_des = (image_text[0]).replace('\n', '')
+
+ if len(image_des)>4 and image_des.startswith("杩欏紶鍥剧墖"):
+ image_des = image_des[4:]
+ self.logger.info(image_des)
+ image_des = self.remove_duplicate_lines(image_des)
+
+ is_waning = 0
+
+ data = {
+ "id": image_id,
+ "event_level_id": res_a[0]['event_level_id'], # event_level_id
+ "event_level_name": res_a[0]['event_level_name'], # event_level_id
+ "rule_id": res_a[0]["rule_id"],
+ "video_point_id": res_a[0]['video_point_id'], # video_point_id
+ "video_point_name": res_a[0]['video_point_name'],
+ "is_waning": is_waning,
+ "zh_desc_class": image_des, # text_vector
+ "bounding_box": res_a[0]['bounding_box'], # bounding_box
+ "task_id": res_a[0]['task_id'], # task_id
+ "task_name": res_a[0]['task_name'], # task_id
+ "detect_id": res_a[0]['detect_id'], # detect_id
+ "detect_time": res_a[0]['detect_time'], # detect_time
+ "detect_num": res_a[0]['detect_num'],
+ "waning_value": res_a[0]['waning_value'],
+ "image_path": res_a[0]['image_path'], # image_path
+ "image_desc_path": res_a[0]['image_desc_path'], # image_path
+ "video_path": res_a[0]['video_path'],
+ "text_vector": res_a[0]['text_vector']
+ }
+ # 淇濆瓨鍒癿ilvus
+ image_id = self.collection.upsert(data).primary_keys
+ data = {
+ "id": str(image_id[0]),
+ "video_point_id": res_a[0]['video_point_id'],
+ "video_path": res_a[0]["video_point_name"],
+ "zh_desc_class": image_des,
+ "detect_time": res_a[0]['detect_time'],
+ "image_path": f"{res_a[0]['image_path']}",
+ "task_name": res_a[0]["task_name"],
+ "event_level_name": res_a[0]["event_level_name"],
+ "rtsp_address": f"{res_a[0]['video_path']}"
+ }
+
+ data = {'collection_name': "smartrag","data": data,"description":""}
+ requests.post(ragurl+"/insert_json_data",
+ json=data
+ )
+ return image_id
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屾ā鍨嬭В鏋愭椂鍑洪敊:浠诲姟锛歿image_id} :{e}")
+ return 0
+
diff --git a/qwen_test.py b/qwen_test.py
new file mode 100644
index 0000000..13b2187
--- /dev/null
+++ b/qwen_test.py
@@ -0,0 +1,36 @@
+from pymilvus import connections, Collection
+
+import qwen_ollama
+
+config = {}
+with open('./conf.txt', 'r', encoding='utf-8') as file:
+ for line in file:
+ # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+ line = line.strip()
+ # 璺宠繃绌鸿
+ if not line:
+ continue
+ # 鍒嗗壊閿拰鍊�
+ if '=' in line:
+ key, value = line.split('=', 1)
+ # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+ key = key.strip()
+ value = value.strip()
+ # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+ config[key] = value
+
+# 鍒濆鍖朚ilvus闆嗗悎
+connections.connect("default", host=config.get("milvusurl"), port=config.get("milvusport"))
+# 鍔犺浇闆嗗悎
+collection = Collection(name="smartobject")
+collection.load()
+
+detect = qwen_ollama.detect_tasks()
+detect._thread_name = f"1" # 璁剧疆鍚嶇О
+detect.init_logging(f"1")
+# 鍒濆鍖朚ilvus闆嗗悎
+detect.collection = collection
+camera_data = [458671636370953916,458671636370953918,458671636370953922,458671636370953977]
+for image_id in camera_data:
+ print(detect.tark_do(image_id, config.get("ollamaurl"), config.get("ragurl"),config.get("ollamamode")))
+
diff --git a/qwen_vllm.py b/qwen_vllm.py
new file mode 100644
index 0000000..26c96bf
--- /dev/null
+++ b/qwen_vllm.py
@@ -0,0 +1,246 @@
+import asyncio
+import base64
+import io
+import json
+import os
+import re
+
+import requests
+import torch
+import logging
+from PIL import Image
+from logging.handlers import RotatingFileHandler
+
+class detect_tasks():
+ def __init__(self):
+ #绾跨▼鍚嶇О
+ self._thread_name = ''
+
+ # 鍒濆鍖朚ilvus闆嗗悎
+ self.collection = None
+ # 鍒濆鍖杔lm
+ self.llm = None
+
+ def remove_duplicate_lines(self,text):
+ seen = set()
+ result = []
+ for line in text.split('銆�'): # 鎸夊彞鍙峰垎鍓�
+ if line.strip() and line not in seen:
+ seen.add(line)
+ result.append(line)
+ return '銆�'.join(result)
+ def remove_duplicate_lines_d(self,text):
+ seen = set()
+ result = []
+ for line in text.split(','): # 鎸夊彞鍙峰垎鍓�
+ if line.strip() and line not in seen:
+ seen.add(line)
+ result.append(line)
+ return '銆�'.join(result)
+ def remove_duplicate_lines_n(self,text):
+ seen = set()
+ result = []
+ for line in text.split('\n'): # 鎸夊彞鍙峰垎鍓�
+ if line.strip() and line not in seen:
+ seen.add(line)
+ result.append(line)
+ return '銆�'.join(result)
+
+ def init_logging(self,logname):
+ # 鍒涘缓瀹炰緥涓撳睘logger
+ self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+ self.logger.setLevel(logging.INFO)
+ # 閬垮厤閲嶅娣诲姞handler
+ if not self.logger.handlers:
+ handler = RotatingFileHandler(
+ filename=os.path.join("logs", logname+'_log.log'),
+ maxBytes=10 * 1024 * 1024,
+ backupCount=3,
+ encoding='utf-8'
+ )
+ formatter = logging.Formatter(
+ '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+ )
+ handler.setFormatter(formatter)
+ self.logger.addHandler(handler)
+
+ def image_desc(self,image_path):
+ try:
+ image_des = None
+ # 鏋勯�犲妯℃�佹秷鎭�
+ messages = [
+ {
+ "role": "user",
+ "content": [
+ {"type": "text", "text": "璇疯缁嗘弿杩板浘鐗囦腑鐨勭洰鏍囦俊鎭強鐗瑰緛銆傝繑鍥炴牸寮忎负鏁存鏂囧瓧鎻忚堪"},
+ {
+ "type": "image_url",
+ "image_url": {
+ "url": f"data:image/jpeg;base64,{self.image_to_base64(image_path)}"
+ }
+ }
+ ]
+ }
+ ]
+
+ # 鍙戦�佽姹�
+ #self.logger.info("鍙戦�佽姹�")
+ response = self.llm.invoke(messages)
+ if response and response.content:
+ image_des = response.content
+ if len(image_des) > 4 and image_des.startswith("杩欏紶鍥剧墖"):
+ image_des = image_des[4:]
+
+ image_des = self.remove_duplicate_lines(image_des)
+ image_des = self.remove_duplicate_lines_d(image_des)
+ image_des = self.remove_duplicate_lines_n(image_des)
+ #self.logger.info(image_des)
+ else:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path, response}")
+ return image_des
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屽浘鐗囨弿杩版椂鍑洪敊:{image_path,e}")
+ return None
+
+ def get_rule(self,ragurl):
+ try:
+ rule_text = None
+ search_data = {
+ "collection_name": "smart_rule",
+ "query_text": "",
+ "search_mode": "hybrid",
+ "limit": 100,
+ "weight_dense": 0.7,
+ "weight_sparse": 0.3,
+ "filter_expr": "",
+ "output_fields": ["text"]
+ }
+ response = requests.post(ragurl + "/search", json=search_data)
+ results = response.json().get('results')
+ rule_text = ""
+ ruleid = 1
+ for rule in results:
+ if rule['score'] >= 0:
+ rule_text = rule_text + str(ruleid) + ". " + rule['entity'].get('text') + ";\n"
+ ruleid = ruleid + 1
+ # self.logger.info(len(rule_text))
+ else:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{response}")
+ return rule_text
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃幏鍙栬鍒欐椂鍑洪敊:{e}")
+ return None
+
+ def image_rule_chat(self, image_des,rule_text, ragurl, rag_mode,max_tokens):
+ try:
+ content = (
+ f"鍥剧墖鎻忚堪鍐呭涓猴細\n{image_des}\n瑙勫垯鍐呭锛歕n{rule_text}銆俓n璇烽獙璇佸浘鐗囨弿杩颁腑鏄惁鏈夌鍚堣鍒欑殑鍐呭锛屼笉杩涜鎺ㄧ悊鍜宼hink銆傝繑鍥炵粨鏋滄牸寮忎负[xxx绗﹀悎鐨勮鍒檌d]锛屽鏋滄病鏈夎繑鍥瀃]")
+ # self.logger.info(content)
+ #self.logger.info(len(content))
+ search_data = {
+ "prompt": "",
+ "messages": [
+ {
+ "role": "user",
+ "content": content
+ }
+ ],
+ "llm_name": rag_mode,
+ "stream": False,
+ "gen_conf": {
+ "temperature": 0.7,
+ "max_tokens": max_tokens
+ }
+ }
+ response = requests.post(ragurl + "/chat", json=search_data)
+ results = response.json().get('data')
+ #self.logger.info(len(results))
+ # self.logger.info(results)
+ ret = re.sub(r'<think>.*?</think>', '', results, flags=re.DOTALL)
+ ret = ret.replace(" ", "").replace("\t", "").replace("\n", "")
+ is_waning = 0
+ if len(ret) > 2:
+ is_waning = 1
+ return is_waning
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛岃鍒欏尮閰嶆椂鍑洪敊:{image_des, rule_text, ragurl, rag_mode,e}")
+ return None
+
+ async def insert_json_data(self, ragurl, data):
+ try:
+ data = {'collection_name': "smartrag", "data": data, "description": ""}
+ requests.post(ragurl + "/insert_json_data", json=data, timeout=(0.3, 0.3))
+ #self.logger.info(f"璋冪敤褰曞儚鏈嶅姟:{ragurl, data}")
+ except Exception as e:
+ #self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿ragurl}锛歿e}")
+ return
+
+ # 澶勭悊澶氭ā鎬佽緭鍏ワ紙绀轰緥锛氭枃鏈�+鍥惧儚锛�
+ def image_to_base64(self,image_path):
+ with open(image_path, "rb") as img_file:
+ return base64.b64encode(img_file.read()).decode('utf-8')
+
+ def tark_do(self,res,ragurl,rag_mode,max_tokens):
+ try :
+ # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ is_waning = 0
+ is_desc = 0
+ #res_a = self.collection.query(
+ # expr=f"id == {image_id}",
+ # output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+ # "task_name","event_level_id","event_level_name",
+ # "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id",
+ # "detect_time", "image_path", "image_desc_path", "video_path"],
+ # consistency_level="Strong"
+ #)
+ image_des = self.image_desc(f"{res['image_desc_path']}")
+ if image_des:
+ #rule_text = self.get_rule(ragurl)
+ is_waning = self.image_rule_chat(image_des,res['waning_value'],ragurl,rag_mode,max_tokens)
+ is_desc = 2
+ else:
+ is_waning = 0
+ is_desc = 3
+ data = {
+ "id": res['id'],
+ "event_level_id": res['event_level_id'], # event_level_id
+ "event_level_name": res['event_level_name'], # event_level_id
+ "rule_id": res["rule_id"],
+ "video_point_id": res['video_point_id'], # video_point_id
+ "video_point_name": res['video_point_name'],
+ "is_waning": is_waning,
+ "is_desc": is_desc,
+ "zh_desc_class": image_des, # text_vector
+ "bounding_box": res['bounding_box'], # bounding_box
+ "task_id": res['task_id'], # task_id
+ "task_name": res['task_name'], # task_id
+ "detect_id": res['detect_id'], # detect_id
+ "detect_time": res['detect_time'], # detect_time
+ "detect_num": res['detect_num'],
+ "waning_value": res['waning_value'],
+ "image_path": res['image_path'], # image_path
+ "image_desc_path": res['image_desc_path'], # image_desc_path
+ "video_path": res['video_path'],
+ "text_vector": res['text_vector']
+ }
+ # 淇濆瓨鍒癿ilvus
+ image_id = self.collection.upsert(data).primary_keys
+ if is_desc == 2 :
+ data = {
+ "id": str(image_id[0]),
+ "video_point_id": res['video_point_id'],
+ "video_path": res["video_point_name"],
+ "zh_desc_class": image_des,
+ "detect_time": res['detect_time'],
+ "image_path": f"{res['image_path']}",
+ "task_name": res["task_name"],
+ "event_level_name": res["event_level_name"],
+ "rtsp_address": f"{res['video_path']}"
+ }
+ #璋冪敤rag
+ asyncio.run(self.insert_json_data(ragurl, data))
+ return image_id
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氭墽琛屾ā鍨嬭В鏋愭椂鍑洪敊:浠诲姟锛歿 res['id']} :{e}")
+ return 0
+
diff --git a/qwen_vllm_detect.py b/qwen_vllm_detect.py
new file mode 100644
index 0000000..f3af0d1
--- /dev/null
+++ b/qwen_vllm_detect.py
@@ -0,0 +1,256 @@
+# 绂佺敤tokenizer骞惰锛堝繀椤绘斁鍦ㄦ墍鏈塱mport涔嬪墠锛�
+from operator import itemgetter
+
+import torch
+import threading
+import time as time_sel
+from typing import Dict
+
+import qwen_vllm
+import requests
+import os
+
+import logging
+from transformers import AutoProcessor, AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+import get_mem
+from langchain_openai import ChatOpenAI
+
+from qwen_vllm_thread import qwen_vllm_thread
+
+
+class ThreadPool:
+ def __init__(self):
+ #璇诲彇閰嶇疆鏂囦欢
+ self.config = {}
+ with open('./conf.txt', 'r', encoding='utf-8') as file:
+ for line in file:
+ # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+ line = line.strip()
+ # 璺宠繃绌鸿
+ if not line:
+ continue
+ # 鍒嗗壊閿拰鍊�
+ if '=' in line:
+ key, value = line.split('=', 1)
+ # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+ key = key.strip()
+ value = value.strip()
+ # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+ self.config[key] = value
+ # 閰嶇疆鏃ュ織
+ # 纭繚鏃ュ織鐩綍瀛樺湪
+ log_dir = "logs"
+ os.makedirs(log_dir, exist_ok=True)
+ self.threads: Dict[str, threading.Thread] = {}
+ self.lock = threading.Lock()
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+ # 鍔犺浇闆嗗悎
+ self.collection = Collection(name="smartobject")
+ self.collection.load()
+ #鏄惁鏇存柊
+ self._isupdate = False
+
+ # 鍒濆鍖栧叡浜唴瀛�
+ get_mem.smem_init()
+
+ # 閰嶇疆鏃ュ織
+ logging.basicConfig(
+ level=logging.INFO,
+ format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S',
+ handlers=[
+ # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+ RotatingFileHandler(
+ filename=os.path.join(log_dir, 'start_log.log'),
+ maxBytes=10 * 1024 * 1024, # 10MB
+ backupCount=3,
+ encoding='utf-8'
+ ),
+ # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+ logging.StreamHandler()
+ ]
+ )
+
+ #鍚姩绾跨▼
+ def safe_start(self, target_func, camera_id):
+ """绾跨▼瀹夊叏鍚姩鏂规硶"""
+ def wrapped():
+ thread_name = threading.current_thread().name
+ try:
+ target_func(camera_id)
+ except Exception as e:
+ logging.error(f"绾跨▼寮傚父: {str(e)}", exc_info=True)
+
+ with self.lock: # 纭繚绾跨▼瀹夊叏鍒涘缓
+ t = threading.Thread(
+ target=wrapped,
+ daemon=True # 璁剧疆涓哄畧鎶ょ嚎绋�
+ )
+ t.start()
+ self.threads[camera_id] = t
+ return t
+
+ # 鍚姩绾跨▼浠诲姟
+ def worker(self, camera_id):
+ pool = qwen_vllm_thread(int(self.config.get("threadnum")),camera_id,self.config)
+ while True:
+ try:
+ res_a = self.collection.query(
+ expr=f"is_desc == 0 and video_point_id=={camera_id}",
+ output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "video_point_name", "task_id",
+ "task_name", "event_level_id", "event_level_name",
+ "video_point_id", "detect_num", "is_waning", "is_desc","waning_value", "rule_id", "detect_id",
+ "detect_time", "image_path", "image_desc_path", "video_path"],
+ consistency_level="Strong",
+ order_by_field="id", # 鎸塱d瀛楁鎺掑簭
+ order_by_type="desc" # 闄嶅簭鎺掑垪
+ )
+
+ # 璇诲彇鍏变韩鍐呭瓨涓殑鍥剧墖
+ # image_id = get_mem.smem_read_frame_qianwen(camera_id)
+ if len(res_a) > 0:
+ sorted_results = sorted(res_a, key=itemgetter("id"), reverse=True)
+ # 鏌ヨ鍓峃涓渶澶х殑ID
+ num = int(self.config.get("threadnum"))-1
+ res_a = sorted_results[:num]
+ for res in res_a:
+ data = {
+ "id": res['id'],
+ "event_level_id": res['event_level_id'], # event_level_id
+ "event_level_name": res['event_level_name'], # event_level_id
+ "rule_id": res["rule_id"],
+ "video_point_id": res['video_point_id'], # video_point_id
+ "video_point_name": res['video_point_name'],
+ "is_waning": 0,
+ "is_desc": 1,
+ "zh_desc_class": res['zh_desc_class'], # text_vector
+ "bounding_box": res['bounding_box'], # bounding_box
+ "task_id": res['task_id'], # task_id
+ "task_name": res['task_name'], # task_id
+ "detect_id": res['detect_id'], # detect_id
+ "detect_time": res['detect_time'], # detect_time
+ "detect_num": res['detect_num'],
+ "waning_value": res['waning_value'],
+ "image_path": res['image_path'], # image_path
+ "image_desc_path": res['image_desc_path'], # image_desc_path
+ "video_path": res['video_path'],
+ "text_vector": res['text_vector']
+ }
+ #logging.info(f"璇诲彇鍥惧儚鎴愬姛: {res['id']}")
+ # 淇濆瓨鍒癿ilvus
+ image_id = self.collection.upsert(data).primary_keys
+ res['id'] = image_id[0]
+ #logging.info(f"璇诲彇鍥惧儚鎴愬姛: {image_id}")
+ image_id = pool.submit(res)
+ #image_id = pool.tark_do(image_id,self.config.get("ragurl"),self.config.get("ragmode"),self.config.get("max_tokens"))
+ #logging.info(f"澶勭悊鍥惧儚鎴愬姛: {image_id}")
+ sorted_results = None
+ except Exception as e:
+ logging.info(f"{camera_id}绾跨▼閿欒:{e}")
+
+ #璋冪敤鏄惁闇�瑕佹洿鏂�
+ def isUpdate(self):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("isupdateurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json().get("data")
+ if data.get("isChange") == 1:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"璋冪敤鏄惁闇�瑕佹洿鏂版椂鍑洪敊:URL:{self.config.get('isupdateurl')}:{e}")
+ return False
+
+ #淇敼鏄惁鏇存柊鐘舵��
+ def update_status(self):
+ try:
+ # 鏇存柊鐘舵��
+ url = self.config.get("updatestatusurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.post(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ return True
+ else:
+ return False
+ except Exception as e:
+ logging.info(f"淇敼鏄惁鏇存柊鐘舵�佹椂鍑洪敊:URL:{self.config.get('updatestatusurl')}:{e}")
+ return False
+
+ def shutdown_all(self) -> None:
+ """娓呯悊鎵�鏈夌嚎绋�"""
+ with self.lock:
+ for camera_id, thread in list(self.threads.items()):
+ if thread.is_alive():
+ thread.join(timeout=1)
+ del self.threads[camera_id]
+
+ #鑾峰彇浠诲姟
+ def getTaskconf(self,isupdate):
+ try:
+ # 瀹氫箟璇锋眰鐨� URL
+ url = self.config.get("gettaskconfurl")
+ # 鍙戦�� GET 璇锋眰
+ response = requests.get(url)
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json()
+ if isupdate:
+ # 鏇存柊鐘舵��
+ self.update_status()
+ return data.get("data")
+ else:
+ return []
+ except Exception as e:
+ logging.info(f"璋冪敤鑾峰彇浠诲姟鏃跺嚭閿�:URL:{self.config.get('gettaskconfurl')}:{e}")
+ return []
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+ pool = ThreadPool()
+ is_init = True
+ camera_data = pool.getTaskconf(False)
+ while True:
+ try:
+ pool._isupdate = False # 鏄惁鏇存柊鏁版嵁
+ # 鏄惁闇�瑕佹洿鏂颁换鍔℃暟鎹�
+ if pool.isUpdate():
+ # 鑾峰彇鎽勫儚鏈轰换鍔�
+ camera_data = pool.getTaskconf(True)
+ pool._isupdate = True # 鏇存柊鏁版嵁
+
+ if is_init:
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ if pool._isupdate:
+ logging.info(f"鏇存柊绾跨▼寮�濮�")
+ pool.shutdown_all()
+ if camera_data:
+ for camera in camera_data:
+ thread = pool.threads.get(camera.get("camera_id"))
+ if not thread:
+ logging.info(f"寮�濮嬪垱寤簕camera.get('camera_id')}绾跨▼")
+ pool.safe_start(pool.worker, camera.get('camera_id'))
+ logging.info(f"{camera.get('camera_id')}绾跨▼鍒涘缓瀹屾瘯")
+
+ logging.info(f"鏇存柊绾跨▼缁撴潫")
+
+ is_init = False
+ time_sel.sleep(1)
+ except Exception as e:
+ logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/qwen_vllm_thread.py b/qwen_vllm_thread.py
new file mode 100644
index 0000000..993b747
--- /dev/null
+++ b/qwen_vllm_thread.py
@@ -0,0 +1,91 @@
+from datetime import datetime
+import logging
+import os
+from concurrent.futures import ThreadPoolExecutor
+import threading
+from logging.handlers import RotatingFileHandler
+from langchain_openai import ChatOpenAI
+from pymilvus import connections, Collection
+import qwen_vllm
+
+
+def process_task(detect,image_id,ragurl,ragmode,max_tokens):
+ image_id = detect.tark_do(image_id,ragurl,ragmode,max_tokens)
+ print(f"瀹屾垚浠诲姟 {image_id} (鑰楁椂: {10:.2f}s)")
+ return image_id
+
+
+class qwen_vllm_thread:
+ def __init__(self, max_workers,camera_id,config):
+ self.executor = ThreadPoolExecutor(max_workers=max_workers)
+ self.semaphore = threading.Semaphore(max_workers)
+ self.max_workers = max_workers
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=config.get("milvusurl"), port=config.get("milvusport"))
+ # 鍔犺浇闆嗗悎
+ self.collection = Collection(name="smartobject")
+ self.collection.load()
+
+ # 鍒濆鍖朙angChain瀹㈡埛绔�
+ self.llm = ChatOpenAI(
+ model=config.get("vllmmode"), # 涓�--served-model-name涓�鑷�
+ temperature=0.7,
+ max_tokens=200,
+ base_url=config.get("vllmurl"),
+ api_key="EMPTY"
+ )
+ self.config = config
+ # 鍒濆鍖�
+ self.detect = qwen_vllm.detect_tasks()
+ self.detect._thread_name = f"{camera_id}" # 璁剧疆鍚嶇О
+ self.detect.init_logging(f"{camera_id}")
+ # 鍒濆鍖朚ilvus闆嗗悎
+ self.detect.collection = self.collection
+ self.detect.llm = self.llm
+ # 鍒涘缓瀹炰緥涓撳睘logger
+ self.logger = logging.getLogger(f"{self.__class__}_{id(self)}")
+ self.logger.setLevel(logging.INFO)
+ # 閬垮厤閲嶅娣诲姞handler
+ if not self.logger.handlers:
+ handler = RotatingFileHandler(
+ filename=os.path.join("logs", 'thread_log.log'),
+ maxBytes=10 * 1024 * 1024,
+ backupCount=3,
+ encoding='utf-8'
+ )
+ formatter = logging.Formatter(
+ '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s'
+ )
+ handler.setFormatter(formatter)
+ self.logger.addHandler(handler)
+
+ def submit(self,res_a):
+ # 灏濊瘯鑾峰彇淇″彿閲忥紙闈為樆濉烇級
+ acquired = self.semaphore.acquire(blocking=False)
+
+ if not acquired:
+ self.logger.info(f"绾跨▼姹犲凡婊★紝绛夊緟绌洪棽绾跨▼... (褰撳墠娲昏穬: {self.max_workers - self.semaphore._value}/{self.max_workers})")
+ # 闃诲绛夊緟鐩村埌鏈夊彲鐢ㄧ嚎绋�
+ self.semaphore.acquire(blocking=True)
+
+ future = self.executor.submit(self._wrap_task, res_a)
+ future.add_done_callback(self._release_semaphore)
+ return future
+
+ def _wrap_task(self, res):
+ try:
+ #self.logger.info(f"澶勭悊: { res['id']}寮�濮�")
+ current_time = datetime.now()
+ image_id = self.detect.tark_do(res, self.config.get("ragurl"), self.config.get("ragmode"), self.config.get("max_tokens"))
+ self.logger.info(f"澶勭悊: { res['id']}瀹屾瘯{image_id}:{datetime.now() - current_time}")
+ return image_id
+ except Exception as e:
+ self.logger.info(f"浠诲姟 { res['id']} 澶勭悊鍑洪敊: {e}")
+ raise
+
+ def _release_semaphore(self, future):
+ self.semaphore.release()
+ self.logger.info(f"閲婃斁绾跨▼ (鍓╀綑绌洪棽: {self.semaphore._value}/{self.max_workers})")
+
+ def shutdown(self):
+ self.executor.shutdown()
diff --git a/smart_detecttest1111.py b/smart_detecttest1111.py
new file mode 100644
index 0000000..a2a2113
--- /dev/null
+++ b/smart_detecttest1111.py
@@ -0,0 +1,261 @@
+
+import threading
+import time as time_sel
+from typing import Dict
+
+import cv2
+import numpy as np
+
+import detect_task
+from datetime import time
+import requests
+import os
+from datetime import datetime
+import torch
+import logging
+import jieba.posseg as pseg
+from transformers import AutoModel, AutoTokenizer, AutoModelForCausalLM, AutoConfig, AutoProcessor, \
+ AutoModelForVision2Seq
+from pymilvus import connections, Collection
+from logging.handlers import RotatingFileHandler
+
+class ThreadPool:
+ def __init__(self):
+ #璇诲彇閰嶇疆鏂囦欢
+ self.config = {}
+ with open('./conf.txt', 'r', encoding='utf-8') as file:
+ for line in file:
+ # 鍘婚櫎姣忚鐨勯灏剧┖鐧藉瓧绗︼紙鍖呮嫭鎹㈣绗︼級
+ line = line.strip()
+ # 璺宠繃绌鸿
+ if not line:
+ continue
+ # 鍒嗗壊閿拰鍊�
+ if '=' in line:
+ key, value = line.split('=', 1)
+ # 鍘婚櫎閿拰鍊肩殑棣栧熬绌虹櫧瀛楃
+ key = key.strip()
+ value = value.strip()
+ # 灏嗛敭鍊煎娣诲姞鍒板瓧鍏镐腑
+ self.config[key] = value
+
+ self.threads: Dict[str, threading.Thread] = {}
+ self.lock = threading.Lock()
+ # 閰嶇疆鏃ュ織
+ # 纭繚鏃ュ織鐩綍瀛樺湪
+ log_dir = "logs"
+ os.makedirs(log_dir, exist_ok=True)
+
+
+ self.device = "cuda:0" if torch.cuda.is_available() else "cpu"
+
+ # 鍒濆鍖栧悜閲忔ā鍨�
+ self.qwen_tokenizer = AutoProcessor.from_pretrained("Qwen2-VL-2B", trust_remote_code=True)
+ self.qwen_model = AutoModelForVision2Seq.from_pretrained("Qwen2-VL-2B", device_map="auto",
+ trust_remote_code=True).eval()
+ # 鍒濆鍖朚ilvus闆嗗悎
+ connections.connect("default", host=self.config.get("milvusurl"), port=self.config.get("milvusport"))
+ # 鍔犺浇闆嗗悎
+ self.collection = Collection(name="smartobject")
+ self.collection.load()
+
+ # 閰嶇疆鏃ュ織
+ logging.basicConfig(
+ level=logging.INFO,
+ format='%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s: %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S',
+ handlers=[
+ # 鎸夊ぇ灏忚疆杞殑鏃ュ織鏂囦欢锛堟渶澶�10MB锛屼繚鐣�3涓浠斤級
+ RotatingFileHandler(
+ filename=os.path.join(log_dir, 'start_log.log'),
+ maxBytes=10 * 1024 * 1024, # 10MB
+ backupCount=3,
+ encoding='utf-8'
+ ),
+ # 鍚屾椂杈撳嚭鍒版帶鍒跺彴
+ logging.StreamHandler()
+ ]
+ )
+
+ def cross_collection_vector_compare(self,image_id,video_point_id,rule_id,video_image_time,frame_id,task_id,video_path,videotaskurl):
+ try:
+ # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ res_a = self.collection.query(
+ expr=f"id in {image_id}",
+ output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+ "video_point_id", "detect_num", "detect_id", "detect_time", "image_path", "video_path"],
+ consistency_level="Strong"
+ )
+
+ # 2. 浠庨泦鍚圔鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ res_b = self.collection_rule.query(
+ expr=f"rule_id in {rule_id}",
+ output_fields=["id", "zh_desc_class", "text_vector","range_value"],
+ consistency_level="Strong"
+ )
+
+ # 3. 璁$畻涓や袱鐩镐技搴�
+ results = []
+ pos_weights = {
+ ('n', 'n'): 1.0, # 鍚嶈瘝鍖归厤
+ ('v', 'v'): 0.8, # 鍔ㄨ瘝鍖归厤
+ ('n', 'v'): 0.3 # 鍚嶈瘝-鍔ㄨ瘝浜ゅ弶
+ }
+ # 寰幆缁撴灉闆�
+ for item_a in res_a:
+ if item_a["detect_num"]>0 : # 鏈夋娴嬪埌鐩爣鏃惰繘琛屾瘮瀵�
+ for item_b in res_b: # 鍜屾瘡涓鍒欓」杩涜瀵规瘮
+ similarity = 0
+ # 1. 鍚戦噺鐩镐技搴︼紙60%鏉冮噸锛�
+ # 灏嗗悜閲忚浆涓簄umpy鏁扮粍
+ vec_a = np.array(item_a["text_vector"])
+ vec_b = np.array(item_b["text_vector"])
+ assert vec_a.shape == vec_b.shape, f"缁村害涓嶅尮閰�: {vec_a.shape} vs {vec_b.shape}"
+ vec_a = vec_a.astype(np.float64) # 鎻愬崌璁$畻绮惧害
+ vec_b = vec_b.astype(np.float64)
+ # 璁$畻鐩镐技搴�
+ vector_sim = np.dot(vec_a, vec_b) / (np.linalg.norm(vec_a) * np.linalg.norm(vec_b))
+
+ # 2. 璇嶆�у尮閰嶅害锛�40%鏉冮噸锛�
+ desc_a = ast.literal_eval(item_a['zh_desc_class']) # 鑾峰彇鐩爣璇箟
+ desc_b = ast.literal_eval(item_b['zh_desc_class'])
+ for clas_a in desc_a: # 鍜屾瘡涓洰鏍囪涔夎繘琛屽姣�
+ pos_match = 0
+ for (_, pos_a, _), (_, pos_b, _) in zip(clas_a, desc_b):
+ pos_match += pos_weights.get((pos_a, pos_b), 0)
+ pos_match /= max(len(clas_a), len(desc_b))
+
+ #鎸夋潈閲嶇粍瑁� 褰撳墠鐩镐技搴� 骞惰祴鍊兼渶澶у��
+ stem_int = 0.6 * vector_sim + 0.4 * pos_match
+ if stem_int > similarity:
+ similarity = stem_int
+
+ # 3.鐩镐技搴﹀鏋滃ぇ浜庤鍒欏尮閰嶉槇鍊�,缁勮棰勮鏁版嵁
+ if similarity > item_b["range_value"]:
+ logging.info(f"鐩镐技搴︼細{similarity}锛歿item_a['zh_desc_class']} {item_b['zh_desc_class']}")
+ results.append({
+ "a_id": item_a["id"],
+ "b_id": item_b["id"],
+ "similarity": round(float(similarity), 4)
+ })
+
+ # 4. 鎸夌浉浼煎害鎺掑簭
+ if len(results) > 0:
+ comparison_results = sorted(results, key=lambda x: x["similarity"], reverse=True) # 闆嗗悎鎺掑簭
+ # 淇濆瓨褰曞儚瑙嗛
+ asyncio.run(self.video_task(video_point_id,video_image_time,"basic",frame_id,video_path,videotaskurl))
+ # 淇濆瓨鍒癿ilvus
+ self.update_milvus(image_id,res_a,1,comparison_results[0]['similarity'],rule_id)
+ else:
+ self.update_milvus(image_id,res_a,0,0.0,rule_id)
+ except Exception as e:
+ self.logger.info(f"{video_point_id}绾跨▼锛氳鍒欏姣旀椂鍑洪敊:{image_id,rule_id}锛� {e}")
+
+ #鍚姩褰曞儚
+ async def video_task(self,video_point_id,video_image_time,task_id,frame_id,video_path,videotaskurl):
+ try:
+ json_data = {
+ "cameraId": f"{video_point_id}",
+ "timestamp": video_image_time,
+ "preSeconds": 10,
+ "postSeconds": 10,
+ "taskId": task_id,
+ "fid": frame_id,
+ "uploadUrl": video_path,
+ "uploadType": "local"
+ }
+ self.logger.info(f"{video_point_id}绾跨▼锛氳皟鐢ㄥ綍鍍忔湇鍔�:{videotaskurl, json_data}")
+
+ # 瀹氫箟璇锋眰鐨� URL
+ # 鍙戦�� GET 璇锋眰
+ response = requests.post(videotaskurl,json=json_data,timeout=(0.03, 0.03))
+ # 妫�鏌ュ搷搴旂姸鎬佺爜
+ if response.status_code == 200:
+ data = response.json()
+ print(data)
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氳皟鐢ㄥ綍鍍忔椂鍑洪敊:鍦板潃锛歿videotaskurl}锛歿e}")
+
+ def update_milvus(self,image_id,res_a,is_waning,similarity,rule_id_list):
+ try:
+ # 淇濆瓨鍒癿ilvus
+ self.collection.upsert(
+ data=[{
+ "id": image_id[0],
+ "text_vector": res_a[0]["text_vector"],
+ "is_waning": is_waning,
+ "waning_value": similarity,
+ "rule_id": rule_id_list,
+ "zh_desc_class": res_a[0]['zh_desc_class'], # text_vector
+ "bounding_box": res_a[0]['bounding_box'], # bounding_box
+ "object_label": res_a[0]['object_label'], # desc
+ "task_id": res_a[0]['task_id'], # task_id
+ "event_level_id": res_a[0]['event_level_id'], # event_level_id
+ "video_point_id": res_a[0]['video_point_id'], # video_point_id
+ "detect_num": res_a[0]['detect_num'],
+ "detect_id": res_a[0]['detect_id'], # detect_id
+ "detect_time": res_a[0]['detect_time'], # detect_time
+ "image_path": res_a[0]['image_path'], # image_path
+ "video_path": res_a[0]['video_path'] # video_path
+ }]
+ )
+ except Exception as e:
+ self.logger.info(f"{self._thread_name}绾跨▼锛氳鍒欏姣斿悗淇敼鏁版嵁鏃跺嚭閿�:{image_id}锛氭槸鍚﹂璀is_waning}锛氶璀﹀�硷細{similarity}锛氳鍒檌d:{rule_id_list}:鏁版嵁闆嗗悎锛歿len(res_a)} :{e}")
+
+ def tark_do():
+ try :
+ # 1. 浠庨泦鍚圓鑾峰彇鍚戦噺鍜屽厓鏁版嵁
+ res_a = collection.query(
+ expr=f"id == {image_id}",
+ output_fields=["id", "zh_desc_class", "text_vector", "bounding_box", "object_label", "task_id", "event_level_id",
+ "video_point_id", "detect_num", "is_waning", "waning_value", "rule_id", "detect_id", "detect_time", "image_path", "video_path"],
+ consistency_level="Strong"
+ )
+ # 鍥剧墖鍜岃棰戝湴鍧�
+ image = Image.open(image_path) # 鏇挎崲涓烘偍鐨勫浘鐗囪矾寰�
+ image = image.thumbnail((512, 512))
+ text = "鎻忚堪杩欏紶鍥剧墖鐨勫唴瀹�"
+ # 澶勭悊杈撳叆
+ inputs = qwen_tokenizer(text=text, images=image, return_tensors="pt").to("cuda")
+ # 鐢熸垚杈撳嚭
+ with torch.no_grad():
+ outputs = qwen_model.generate(**inputs, max_new_tokens=50)
+ response = qwen_tokenizer.decode(outputs[0], skip_special_tokens=True)
+ print(response)
+
+ # 淇濆瓨鍒癿ilvus
+ collection.upsert(
+ data=[{
+ "id": image_id,
+ "text_vector": res_a[0]["text_vector"],
+ "is_waning": res_a[0]["is_waning"],
+ "waning_value": res_a[0]["waning_value"],
+ "rule_id": res_a[0]["rule_id"],
+ "zh_desc_class": res_a[0]['zh_desc_class'], # text_vector
+ "bounding_box": res_a[0]['bounding_box'], # bounding_box
+ "object_label": f"{response}", # desc
+ "task_id": res_a[0]['task_id'], # task_id
+ "event_level_id": res_a[0]['event_level_id'], # event_level_id
+ "video_point_id": res_a[0]['video_point_id'], # video_point_id
+ "detect_num": res_a[0]['detect_num'],
+ "detect_id": res_a[0]['detect_id'], # detect_id
+ "detect_time": res_a[0]['detect_time'], # detect_time
+ "image_path": res_a[0]['image_path'], # image_path
+ "video_path": res_a[0]['video_path'] # video_path
+ }]
+ )
+ print(f"鎵ц浠诲姟{image_id,image_path}锛氱粨鏉�")
+ return 1
+ except Exception as e:
+ print(f"鎵ц妯″瀷瑙f瀽鏃跺嚭閿�:{image_id,image_path} :{e}")
+ return 0
+
+
+# 浣跨敤绀轰緥
+if __name__ == "__main__":
+ pool = ThreadPool()
+ while True:
+ try:
+ pool.tark_do()
+ except Exception as e:
+ logging.info(f"涓荤嚎绋嬫湭鐭ラ敊璇�:{e}")
diff --git a/temp.jpg b/temp.jpg
new file mode 100644
index 0000000..2841ca1
--- /dev/null
+++ b/temp.jpg
Binary files differ
diff --git a/vllm.py b/vllm.py
new file mode 100644
index 0000000..bb4814f
--- /dev/null
+++ b/vllm.py
@@ -0,0 +1,62 @@
+import torch
+from modelscope import Qwen2_5_VLForConditionalGeneration, AutoTokenizer, AutoProcessor
+from qwen_vl_utils import process_vision_info
+
+# default: Load the model on the available device(s)
+model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
+ "Qwen2.5-VL-3B-Instruct-AWQ", torch_dtype=torch.float16, device_map="auto"
+)
+
+# We recommend enabling flash_attention_2 for better acceleration and memory saving, especially in multi-image and video scenarios.
+# model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
+# "Qwen/Qwen2.5-VL-3B-Instruct-AWQ",
+# torch_dtype=torch.bfloat16,
+# attn_implementation="flash_attention_2",
+# device_map="auto",
+# )
+
+# default processer
+processor = AutoProcessor.from_pretrained("Qwen2.5-VL-3B-Instruct-AWQ")
+
+# The default range for the number of visual tokens per image in the model is 4-16384.
+# You can set min_pixels and max_pixels according to your needs, such as a token range of 256-1280, to balance performance and cost.
+# min_pixels = 256*28*28
+# max_pixels = 1280*28*28
+# processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct-AWQ", min_pixels=min_pixels, max_pixels=max_pixels)
+
+messages = [
+ {
+ "role": "user",
+ "content": [
+ {
+ "type": "image",
+ "image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg",
+ },
+ {"type": "text", "text": "Describe this image."},
+ ],
+ }
+]
+
+# Preparation for inference
+text = processor.apply_chat_template(
+ messages, tokenize=False, add_generation_prompt=True
+)
+image_inputs, video_inputs = process_vision_info(messages)
+inputs = processor(
+ text=[text],
+ images=image_inputs,
+ videos=video_inputs,
+ padding=True,
+ return_tensors="pt",
+)
+inputs = inputs.to("cuda")
+
+# Inference: Generation of the output
+generated_ids = model.generate(**inputs, max_new_tokens=128)
+generated_ids_trimmed = [
+ out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
+]
+output_text = processor.batch_decode(
+ generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
+)
+print(output_text)
\ No newline at end of file
--
Gitblit v1.8.0